Длительные операции (потоки) в сети (asp.net) среда

У меня есть asp.net (mvc) веб-сайт. Как часть функций я должен буду поддерживать некоторые длительные операции, например:

Инициируемый от пользователя: Пользователь может загрузить (xml) файл на сервер. На сервере я должен извлечь файл, сделать некоторое управление (вставьте в дб), и т.д... Это может занять с без одной минуты десять минуты (или еще более - зависит от размера файла). Конечно, я не хочу блокировать запрос, когда импорт работает, но я хочу перенаправить пользователя к некоторой странице прогресса, где у него будет шанс наблюдать состояние, ошибки или даже отменить импорт.

Эта операция не будет часто использоваться, но это может произойти, что два пользователя одновременно попытаются импортировать данные. Было бы хорошо выполнить импорт параллельно. Вначале я думал, чтобы создать новый поток в iis (действие контроллера) и выполнить импорт в новом потоке. Но я не уверен - ли это хорошая идея (для создания рабочих потоков на веб-сервере). Я должен использовать услуги окон или какой-либо другой подход?

Инициируемый от системы: - я должен буду периодически обновлять индекс lucene с новыми данными. - Я должен буду послать массовые электронные письма (в будущем).

Я должен реализовать это как задание в сайте и выполнить задание с помощью Quartz.net, или я должен также создать сервис окон или что-то?

Каковы лучшие практики когда дело доходит до рабочего сайта "задания"?

Спасибо!

10
задан rrejc 11 May 2010 в 07:07
поделиться

3 ответа

Я бы реализовал отдельную службу windows для долго выполняющихся задач. Веб-приложение делегирует долго выполняющиеся задачи этой службе с помощью подхода очереди. Как организовать очередь задач - решать вам. Будет ли задача в очереди иметь приоритет, максимальное время выполнения или нет. Очередь может быть реализована как обычная таблица (таблицы) в СУБД, которая содержит свойства информации о статусе выполнения задания (довольно простой подход).

Таким образом, обычный сценарий может выглядеть следующим образом:

  • Клиент отправляет всю необходимую информацию веб-серверу

  • Веб-сервер передает задание сервису и уведомляет клиента - задача была успешно поставлена в очередь (идентификатор задачи также отправляется клиенту)

  • Внешний сервис начинает обработку задачи, обновляя информацию о ходе выполнения.

  • Клиент начинает опрашивать веб-сервер с помощью короткие запросы о выполнении задания (с полученным ранее идентификатором) статусе и ходе выполнения.

Вы можете выбрать разные технологии (Windows Service + DB / WCF Service) и разные подходы к взаимодействию (polling, pushing, callbacks), но я советую делегировать долгоиграющие задачи внешнему сервису (не выполнять их внутри веб-приложения).

Выполнение длительных задач приводит к модели thread-per-request (в терминах многопоточного программирования). Эта модель имеет плохую масштабируемость и ограничения на максимальное количество потоков в пуле потоков. Однако это не ваш случай :)

6
ответ дан 4 December 2019 в 01:00
поделиться

Я успешно реализовал сценарий, похожий на этот, с помощью jQuery. в основном, я использую функцию beforeSend : для отображения страницы типа «подождите». вот основной код в игре (также я не могу, вы также можете использовать базовый класс AsyncController , чтобы сделать действие асинхронным):

<script type="text/javascript">
    $(document).ready(function() {
        $('#create').bind('click', function() {
            saveFundProperty();
        });
    });

    // main functions
    function saveFundProperty() {
        var url = '<%= Url.Action("Create", "FundProperty") %>';
        var params = { fundId: $("#FundID").val(), propertyId: $("#PropertyID").val() };
        SendAjax(url, params, beforeQuery, saveFundPropertyResponse);
    }

    function beforeQuery() {
        var url = '<%= Url.Action("Wait", "FundProperty") %>';
        $("#statusMsg").load(url);
    }

    function saveFundPropertyResponse(data) {
        if (data.length != 0) {
            if (data.indexOf("ERROR:") >= 0) {
                $("#statusMsg").html(data).css('backgroundColor','#eeaa00');
            }
            else {
                $("#statusMsg").html(data);
            }
        }
    }
</script>

надеюсь, что это поможет.

Метод SendAjax - это просто функция-оболочка, чтобы сделать вещи немного более согласованными. вот он полностью:

<script type="text/javascript">
function SendAjax(urlMethod, jsonData, beforeSendFunction, returnFunction, dataType, contentType) {
    $.ajaxSetup({ cache: false });
    dataType = dataType || "text"; // default return type
    contentType = contentType || "application/x-www-form-urlencoded"; // default input type
    $.ajax({
        type: "POST",
        url: urlMethod,
        data: jsonData,
        dataType: dataType,
        contentType: contentType,
        beforeSend: function() {
            if(beforeSendFunction!==null)
                beforeSendFunction();
        },
        success: function(data) {
            // Do something interesting here.
            if (data != null && returnFunction!==null) {
                returnFunction(data);
            }
        },
        error: function(xhr, status, error) {
            // Boil the ASP.NET AJAX error down to JSON.
            var err = eval("(" + xhr.responseText + ")");

            // Display the specific error raised by the server
            alert(err.Message);
        }
    });
}
</script>

[edit] - не уверен, что происходит с форматированием SendAjax. надеюсь, что это легко скопировать / вставить ...

1
ответ дан 4 December 2019 в 01:00
поделиться

На мой взгляд, длительные задачи обычно всегда следует делегировать операциям, не основанным на пользовательском интерфейсе. Я бы предложил, возможно, службу WF или Window.

4
ответ дан 4 December 2019 в 01:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: