线程.StartNew()和.Wait()

时间:2016-09-29 23:22:54

标签: c# asp.net multithreading task wait

我甚至不假装理解C#中的线程,所以我正在寻找一个关于线程的非常简单的解释 - 更具体地说是.NET 4中的StartNew()功能。

我使用以下方法通过一种“一劳永逸”的方法调用另一种方法。当网页需要启动一个耗时的过程时,我可能会这样做,但页面并不真正需要等待结果。据我了解,DoSomething()方法将以异步方式运行。"

System.Threading.Tasks.Task.Factory.StartNew(() =>
{
    DoSomething();
});

上面的代码似乎就像我想要的那样 - 虽然我有一种偷偷摸摸的怀疑,我并没有真正将它用于预期的目的。在DoSomething()方法运行之前关闭的控制台应用程序中,我也被捕获了。我不确定为什么它适用于网页但不适用于控制台应用程序 - 我假设是因为即使页面已被卸载,应用程序池也会继续运行。

让我感到困惑的是,我已经看到很多例子,他们用.Wait()结束这样的代码。据我了解,.Wait()意味着此页面上的其余代码将等待DoSomething()方法运行...在这种情况下 - 在我有限的理解中 - 这似乎否定了使用的任何好处首先是StartNew()?

我希望有人可以用我简单的小脑子会理解的方式帮助解释这个问题!也许您还可以解释一种使用“即发即弃”方法调用方法的更好方法?非常感谢!

1 个答案:

答案 0 :(得分:2)

System.Threading.Tasks.Task.Factory.StartNew(() =>
{
    DoSomething();
})

这实际上将工作卸载到ThreadPool上。一旦可用,就会使用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本身的线程暂停”。

为什么危险?

  • 与请求无关的线程中的未处理异常将 记下这个过程。
  • 如果您在网络服务器场中运行您的网站,您最终可能会遇到应用程序的多个实例,这些实例都会同时尝试运行相同的任务。
  • 您的网站运行的AppDomain可能由于多种原因而停止运行并取消您的后台任务 用它。

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

如何在ASP.NET应用上运行任务:http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx