Фоновая обработка в .Net - требуется совет - PullRequest
2 голосов
/ 08 февраля 2012

Извините, если это довольно длинный вопрос, мне нужен совет о том, что люди считают лучшим методом (как есть несколько).

На данный момент в моем проекте есть метод

do_job(jobid,userid)

Этот метод занимает минуту или две, а затем перенаправляет на другую страницу.

Этот текст был переписан так, что теперь он работает в фоновом режиме и перенаправляет на другую страницу, пока поток, который делает do_jobпродолжается- Это прекрасно работает.

В событии button_click на странице default.aspx:

Dim d as New do_job_delegate(AddressOf do_job)
d.BeginInvoke(jobid,userid, New AsyncCallback(AddressOf Callback),d)
Response.redirect("results.aspx")

Что относится к

Delegate Sub do_job_delegate(Byval jobid as integer, Byval userid as integer)

Public Sub do_job(Byval jobid as integer, Byval userid as integer)
     ' Do something for several seconds
End Sub

Public Sub Callback(Byval ar As IAsyncResult)
    ar.AsyncState.EndInvoke(ar)
End Sub

Это в основном делает то, что я хочу,пользователь может продолжать выполнять какие-либо действия на сайте, а метод do_job работает в фоновом режиме и успешно выполняет свои задачи.

Однако теперь я добавил этот метод do_job, и есть несколько небольших задач, каждая из которыхзанимает около 30 секунд в do_job, и они могут / должны быть сделаны для параллельной работы.например,

Public Sub do_job(Byval jobid as integer, Byval userid as integer)
     loop through between 1 or more (up to roughly 10 items)
         'process that takes about 30 seconds
     end loop
End Sub

Итак, я хочу, чтобы do_job занимал самое длинное время самой длинной работы (30 секунд), а не - 30 секунд x количество заданий = время, которое требуетсяна данный момент.

Поскольку я уже использую делегата для отсоединения процесса от пользовательского интерфейса, может ли кто-нибудь дать какой-либо совет / наилучшую практику о том, как мне следует перестроить свой метод do_job, чтобы он мог обрабатывать параллельные задачи длядальнейшее повышение общей скорости.

Спасибо!

Ответы [ 2 ]

4 голосов
/ 08 февраля 2012

Я бы порекомендовал, прежде чем тратить на это кучу времени, рассмотреть вопрос о переносе работы в отдельный сервис, а не о запуске ее на своем веб-сервере.

Просто бросьте запись в таблицу базы данных и попросите службу посмотреть ее.

Вот статья Фила Хаака, объясняющая, почему вы не должны связываться с потоками на вашем веб-сервере.

http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx

Что касается параллельного выполнения задач, обратите внимание на библиотеки .net 4.0 Parallel. Они делают такие вещи очень легкими.

http://msdn.microsoft.com/en-us/library/dd460717.aspx

1 голос
/ 08 февраля 2012

Как сказал @BNL, это действительно должно быть сделано в сервисе или другом процессе, существующем вне конвейера веб-запросов / ответов.Потенциально серьезная проблема с вашим текущим подходом заключается в том, что, если вы получаете много трафика, вы создадите гораздо больше потоков, чем ваша система может разумно обработать.Это исключает любые преимущества, которые вы могли бы получить от многопоточности в однопользовательской среде, и, фактически, может привести к таким большим накладным расходам, что вызывает более медленный ответ, чем однопоточный подход.

Рассмотрите возможность описаниязадача, которая должна быть выполнена в таблице базы данных:

id
job_id
user_id
date_created
date_started
date_completed
status_code

, и ваш сервисный опрос этой таблицы, чтобы найти задания, которые необходимо обработать.Это дает вам ряд дополнительных преимуществ, в том числе возможность генерировать отчет об успехах / неудачах, очереди заданий, которые будут сохраняться при сбросе IIS, и т. Д. Если веб-приложение должно предупреждать пользователя о завершении задания, проверьте его.таблица при загрузке страницы (простая) или периодически с помощью AJAX-запроса (менее простая), как это делает StackOverflow при проверке новых ответов на вопрос, который вы читаете.

См. эту статью для обзорасоздания служб в VB.NET.

Если это не удастся, простой способ запустить множество похожих задач параллельно - через Parallel.For и Parallel.ForEach, но я не могу не подчеркнуть, насколькоопасно, что это происходит в сети или в другой многопользовательской среде.

Кроме того, следует различать ASP.NET версия и .NET Framework версия .На многих / большинстве серверов должна быть доступна .NET Framework 4, даже если их сайты используют ASP.NET 2.

См. Эту статью MSDN для примера последнего , нослужба действительно способ идти.

...