Разъяснения по использованию Task Parallel Library с ASP.NET 4.0 - PullRequest
2 голосов
/ 23 февраля 2012

У меня есть веб-форма, где я использую TPL для отправки электронной почты в фоновом режиме, так как наш SMTP-сервер работает медленно, и многие пользователи в итоге разочаровываются в кнопке отправки. В прошлом я использовал System.Threading и статические методы для выполнения аналогичной задачи - в .NET3.5 мой код выглядел так:

Thread t = new Thread(new ParameterizedThreadStart(SendEmail));
t.Start(txtEmail.Text);

Где подпись SendEmail была public static void AddEmailToMailingListInBackground(object EmailString), и, насколько я помню, метод должен был быть статическим, и мне пришлось передать значение TextBox txtEmail асинхронному методу или рискнуть потерять доступ к значению элемента управления, поскольку жизненный цикл страницы продолжался независимо .

Теперь при использовании System.Threading.Tasks мой код выглядит так:

Task.Factory.StartNew(() => SendEmail(), TaskCreationOptions.LongRunning);

и подпись SendEmail private void SendEmail(), и я получаю доступ к свойству Text txtEmail непосредственно в этом методе.

Здесь я вижу два основных различия. Во-первых, мой асинхронный метод больше не должен быть статическим. Во-вторых, я могу получить доступ к контрольным значениям страницы в методе намного позже, чем закончился бы жизненный цикл страницы, если бы я использовал потоки. Эти два момента заставляют меня поверить, что Страница сохраняется, пока не будут выполнены все Задачи или жизненный цикл Страницы, в зависимости от того, что наступит последним. Я проверил это путем отладки и пошагового асинхронного метода - ответ отправляется в браузер, но я все еще могу пройти и получить доступ к элементам управления и их значениям. Эта статья MSDN немного помогает, но все еще не укрепляет мое понимание того, что происходит с TPL, по сравнению с до-NET4 способом выполнения асинхронных вызовов.

Может кто-нибудь сказать мне, если мое мышление правильно, и это надежное поведение при использовании TPL с ASP.NET?
Кто-нибудь хотел бы уточнить дальше?

1 Ответ

3 голосов
/ 23 февраля 2012

Технически не безопасен для доступа к объектам ASP.NET из потока ASP.NET.Было бы гораздо лучше извлечь детали, необходимые SendMail, со страницы / запроса и передать их через закрытие.

Кроме того, вам необходимо убедиться, что вы «наблюдаете» любые исключения, которые могут произойти в SendMail илиTPL вызовет исключение, которое приведет к сбою всего вашего веб-приложения.Вы можете сделать это с помощью попытки / перехвата самого вызова SendMail или цепочки на другом продолжении с опцией TaskContinuationOptions.OnlyOnFapted.В подходе продолжения вам просто нужно получить доступ к свойству Exception антецедента, предположительно для его регистрации, чтобы TPL знал, что вы «наблюдали» исключение.

Итак, чтобы собрать все этоможет выглядеть так:

string userEmail = userEmailTextBox.Text;
// whatever else SendMail might need from the page/request

Task.Factory.StartNew(() => SendMail(userEmail))
            .ContinueWith(sendEmailAntecedent =>
                          {
                              Trace.TraceError(sendEmailAntecedent.Exception.ToString());
                          },
                          TaskContinuationOptions.OnlyOnFaulted|TaskContinuationOptions.ExecuteSynchronously);
...