如果我有一个异步方法:
async Task Process()
{
while (condition)
{
await ...;
}
}
我需要安排此方法的执行时间。所以我用:
Task.Run(Process);
我是否需要保留Task
方法返回的Task.Run
对象的引用,以确保Process
执行完成?
这里有更多上下文:我需要在应用程序中创建很多(约50K)任务队列。因此,我想创建一个无线程的队列处理设计,并且当队列为空时(因为这些队列中的大多数都是这样),它不花钱(除了内存)。
示例类的要点:https://gist.github.com/hemant-jangid/e990b27507596c086e5651f504d0521f
答案 0 :(得分:5)
通常,您不应该丢弃Task
。这不是要确保任务将运行(它将 1 ),而是要观察异常。如果您不使用Task
做 something ,那么找出错误的唯一方法就是添加一个UnobservedTaskException
事件处理程序。不理想。
最好在await
/ try
块中使用catch
的代码,或者在您指定的地方注册ContinueWith
处理程序,以便在发生故障时调用。 / p>
不幸的是(IMO).NET的行为在4.5左右发生了变化,因此无法观察到的异常不再破坏该过程。这意味着,如果您未能观察到它们,则代码将失败,并且没有办法来跟踪/记录这种情况。
在 general 中,围绕已经产生Task.Run
的方法进行Task
是不必要的,而且会适得其反。该方法已经承诺提供Task
-为什么将其包装在第二个方法中? (该方法如何以及为什么返回Task
是该方法的实现细节,而与调用者无关。)只有在您所调用的方法确实完成了重要 CPU绑定工作并且您(调用方)当前处于“宝贵”上下文中时(例如位于UI线程中),您才应该真正这样做。
1 假定整个过程可以生存足够长的时间,等等。
答案 1 :(得分:0)
为此,我们将不得不更深入地研究任务。任务本质上是线程,在其起源中,任务是为线程池安排的。现在考虑以下报价:
任务本质上是线程;但它们是后台线程。 当所有前台都后台线程自动中止 线程完成。因此,如果您对任务不执行任何操作, 程序结束,任务有可能无法完成。
因此您可能会认为,如果在所有前台线程完成后后台线程自动中止,则必须保留对task
的引用,实际上,这就是为什么您应始终等待{ {3}}。
但是让我们深入研究this post answer并查看以下行:
一旦您没有必要保留对Thread对象的引用 已经启动了线程。线程继续执行,直到 线程过程完成。
这意味着,尽管上面提到,当所有前台线程完成时,后台线程会自动中止,但无需保留对其的引用。
实际上,根据文档,创建任务的正确方法是使用工厂:
您还可以使用StartNew方法来创建和启动一个任务 操作。如果存在以下情况,这是创建和启动任务的首选方式 创建和计划不必分开