繁体   English   中英

使用和不使用await运算符执行任务

[英]Task execution with and without await operator

我昨天问了一个问题 ,答案很好。 但现在我正在尝试理解await的角色以及任务执行的工作原理。

我已经读到了await :await运算符应用于异步方法中的任务,以暂停方法的执行,直到等待的任务完成。 该任务代表正在进行的工作(来自msdn网站)。

Task.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);行上设置了断点Console.WriteLine(completed); 为什么即使在这个断点处等待2-3分钟后,任务仍未完成且没有出现故障? 我在任务的代码中设置了一个断点,并且异常被设法,所以任务必须被标记为出错或至少完成...

没人真的回答你的问题。 如果等待超过3秒,您有合理的期望看到task.isCompletedtask.isFaulted为true。

你的期望没错。 这里的问题只是调试器的工作原理。 当你在那个断点处等待停止时,所有其他线程也会停止,所以没有任何进展,并且还没有抛出异常。

这只是一个调试的怪癖,如果你想看到你期望的结果,你有几个选择:

  1. 冻结线程而不是使用断点。 为此,在var task=Task.Run()之后立即设置断点,然后在调试器中打开“线程”窗口。 找到当前线程(用黄色箭头)右键单击它并选择“冻结”然后点击F8或点击继续让应用程序继续运行。 3-4秒后,单击调试器上的“暂停”按钮,然后再次双击冻结的线程。 您现在可以检查task.IsCompletedtask.IsFaulted的值,它们应该是true。
  2. 在检查任务之前添加超时:

码:

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 ,只是在当前线程上同步完成工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM