昨天我问question,答案很好。但现在我正在尝试理解await
的作用以及任务执行的工作原理。
我已经阅读了await
:await运算符应用于异步方法中的任务,以暂停方法的执行,直到等待的任务完成。该任务代表了正在进行的工作(来自msdn网站)。
Task.run
:Run方法允许您在单个方法调用中创建和执行任务,并且是StartNew方法(来自msdn站点)的更简单的替代方法。
现在,使用代码:
public async Task YourFunc()
{
Exception error = null;
try
{
var task = Task.Run(() =>
{
Thread.Sleep(3000);
throw new ArgumentException("test argument exception");
});
var completed = task.IsCompleted;
var faulted = task.IsFaulted;
Console.WriteLine(completed);
Console.WriteLine(faulted);
}
catch (Exception ex)
{
error = ex;
}
this.MigrationProcessCompleted(error);
}
我删除了await运算符,并在行Console.WriteLine(completed);
上设置了断点。为什么即使在这个断点处等待2-3分钟后,任务仍未完成且没有出现故障?我在任务代码中设置了一个断点,并且异常被设法,所以任务必须被标记为出错或至少完成......
答案 0 :(得分:2)
没有人真的回答过你的问题。如果您等待超过3秒,您可以合理地期望task.isCompleted
和task.isFaulted
成立。
你的期望没有错。这里的问题只是调试器的工作原理。当你在那个断点处等待停止时,所有其他线程也会停止,所以没有任何进展,并且还没有抛出异常。
这只是一个调试的怪癖,如果你想看到你期望的结果,你有几个选择:
var task=Task.Run()
之后放置一个断点,然后在调试器中打开“线程”窗口。找到当前线程(用黄色箭头)右键单击它并选择“冻结”然后点击F8或点击继续让应用程序继续运行。 3-4秒后,单击调试器上的“暂停”按钮,然后再次双击冻结的线程。您现在可以查看task.IsCompleted
和task.IsFaulted
的值,它们应该是真的。代码:
var task = Task.Run(() =>{
Thread.Sleep(3000);
throw new ArgumentException("test argument exception");
});
Thread.Sleep(5000);
var completed = task.IsCompleted;
var faulted = task.IsFaulted;
Console.WriteLine("Completed ::" + completed);
Console.WriteLine("Faulted ::" + faulted);
现在,您可以在Thread.Sleep(5000)
之后放置一个断点,并确认该任务出现故障/已完成。
请记住,正如其他人所说,立即awaited
Task.Run()
的用例几乎总是一个错误。请记住,async/await
的重点是释放当前线程,这样就不会无用等待。如果您执行Task.Run
后跟await
,那么您还没有实现任何目标,因为您只是释放当前线程(将其放回线程池中),但Task.Run()
将采用从线程池回来一个线程。从概念上讲,你所做的一切都是将你的工作从一个线程id转移到另一个线程id而没有任何实际收益(即使Task.Run
中的工作受CPU限制)。
在这种情况下,你最好不要做Task.Run
而只是在当前线程上同步完成工作。