Нарезка резьбы.StartNew() и.Подождите()
Я даже не претендую на понимание потоковой обработки в C#, поэтому я ищу действительно простое объяснение потокам - более конкретно функцию StartNew() в .NET 4.
Я использую следующее, чтобы вызвать другой метод с своего рода подходом "пожар и забвение". Я мог бы сделать это, когда веб-странице нужно инициировать трудоемкий процесс, но когда странице на самом деле не нужно ждать результата. Как я понимаю, метод DoSomething() будет выполняться "асинхронно."
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
DoSomething();
});
Вышеприведенный код, похоже, работает именно так, как я хочу, хотя у меня есть смутное подозрение, что я на самом деле не использую его по назначению. Я также был пойман с его помощью в консольных приложениях, которые закрываются до запуска метода DoSomething (). Я не уверен, почему он работает на веб-страницах, но не консольных приложениях - я предполагаю, потому что пул приложений продолжает работать, даже когда страница была выгружена.
Что меня действительно смущает, так это то, что у меня есть видел много примеров, где они заканчиваются таким кодом .Ждать(). Насколько я понимаю, свои .Wait() означает, что остальная часть кода на этой странице будет ждать, пока не будет запущен метод DoSomething ()... в каком случае - в моем ограниченном понимании - это, кажется, сводит на нет все преимущества использования StartNew() в первую очередь?
Я надеюсь, что кто-нибудь поможет мне объяснить это так, чтобы мой простой маленький ум понял! Возможно, вы также можете объяснить лучший способ вызова метода с помощью fire-and-forget подходить? Большое спасибо!1 ответ:
System.Threading.Tasks.Task.Factory.StartNew(() => { DoSomething(); })
Это существенно разгрузит работу на ThreadPool. Поток
ThreadPool
используется, как только он доступен (это означает, что он может быть фактически выполнен в разное время, если пул потоков заполнен).Вызывая
.Wait()
в конце, это будет блокировать, пока эта задача не завершит выполнение. По сути, он не позволит основному потоку работать, пока он не будет завершен, и может привести к проблемам с производительностью в зависимости от того, как долгоDoSomething()
выполняется.Лучший подход заключается в том, чтобы используйте
async/await
, чтобы ваше приложение могло продолжать реагировать, не связывая основнуюThread
.Также обратите внимание, что вы должны использовать
Task.Run
вместоStartNew
. Если только вам не нужно предоставить другие параметры (например, маркер отмены, расписание и т. д.),Task.Run
используется по умолчанию.Например:
// fire and forget, this will run on a thread once one is available on the thread pool Task.Run(()=> { DoSomething(); }); // fire and wait until exeuction has finished. this will block all activity until it is done Task.Run(()=> { DoSomething(); }).Wait(); // fire and and wait until the task is completed but do not block the current thread. private async void DoSomethingAsync() { await Task.Run(()=> { DoSomething(); }); // perform work after }
Примечание: Как отметил VMAtm, " запуск задачи в ASP.NET приложение может быть опасным, так как оно может быть приостановлено с потоком IIS сам ".
Почему это опасно?
- необработанное исключение в потоке, не связанном с запросом, будет снимите этот процесс.
- Если вы запускаете сайт в веб-ферме, вы можете получить несколько экземпляров вашего приложения, которые пытаются выполнить одну и ту же задачу одновременно.
- домен приложений, в котором работает ваш сайт, может отключиться по ряду причин и снять фоновую задачу с ним.
Как запускать задачи на ASP.NET приложение: http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx