我昨天问了一个question,答案是好的。但现在我正在尝试理解await的作用以及任务执行是如何工作的。
我读到过关于await的文章: await操作符应用于异步方法中的任务,以挂起该方法的执行,直到等待的任务完成。该任务表示正在进行的工作(来自msdn站点)。
Task.run:Run方法允许您在单个方法调用中创建和执行任务,并且是StartNew方法(来自msdn site)的一个更简单的替代方法。
现在,使用代码:
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分钟后,任务仍未完成且未出错?我已经在任务的代码中设置了一个断点,并且异常是特洛伊的,所以任务必须标记为出错或至少已完成……
发布于 2016-10-30 20:01:17
没有人真正回答你的问题。如果等待超过3秒,您有一个合理的期望看到task.isCompleted和task.isFaulted为真。
你的期望是正确的。这里的问题很简单,调试器是如何工作的。当您在该断点处停止等待时,所有其他线程也会停止,因此没有任何进展,并且还没有抛出异常。
这只是调试的一种怪癖,如果您想要查看预期的结果,您有几个选择:
var task=Task.Run()之后放置一个断点,然后在调试器中打开“线程”窗口。找到当前线程(带有黄色箭头),右键单击它并选择"freeze“,然后点击F8或单击continue让应用程序继续运行。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)之后放置断点,并确认任务已出错/已完成。
请记住,正如其他人所说,immediately awaited Task.Run()的用例几乎总是错误的。请记住,async/await的主要目的是释放当前线程,这样它就不会做无用的等待。如果您先执行Task.Run,然后执行await,那么您并没有完成任何任务,因为您只是释放了当前线程(将其放回线程池中),但是Task.Run()将直接从线程池中接收回一个线程。从概念上讲,您所做的一切只是将您的工作从一个线程id移动到另一个线程id,而没有任何实际收益(即使您的Task.Run中的工作是受CPU限制的)。
在这种情况下,您最好根本不执行Task.Run,只在当前线程上同步执行工作。
https://stackoverflow.com/questions/40301882
复制相似问题