在使用await语句之后,Task.Result会产生任何影响吗?

14 浏览
0 Comments

在使用await语句之后,Task.Result会产生任何影响吗?

我正在努力开发一个概念验证应用程序,并且我想了解下面两个异步方法的内部工作原理。\n在DoSomethingAsync1()中使用Task.Result会导致任何问题吗?\n我读到过一些关于Task.Result可能引起的阻塞和死锁问题的内容,但我认为在这种情况下不会有问题,因为它在一个单独的任务上运行,并且任务上已经有await关键字来确保结果。\n主要目标是在单独的任务上运行异步方法,因为此操作不依赖于主asp.net线程,并且更重要的是捕获DoSomethingThatTakesReallyLong()抛出的任何异常。\n此外,在ActionResult DoSomething()中,我应该设置.ConfigureAwait(false);吗?\n在下面的场景中,有任何隐藏的瓶颈或问题需要注意吗?\n更新\n我已经纠正了我在这里书写问题时的拼写错误(返回用户对象而不是任务)。\n而且,在实际应用程序中,我没有将所有更高级的方法一次性转换为async。因此,这是我计划逐步进行的一项工作,从不依赖于主线程的操作开始。\n我非常感谢所有最佳实践的答案,但这只是一段小的测试代码,我的主要问题是想知道DoSomethingAsync1()DoSomethingAsync2()之间是否有内部差异,可能在某些条件下导致问题。\n从阅读评论和答案中,我了解到差异不大。\n


\n

  private static async Task DoSomethingAsync1()
    {
        try
        {
            var longRunningTask = Task.Factory.StartNew(() => LongRunner.LongRunnerInstance.DoSomethingThatTakesReallyLong());
            var user = await longRunningTask;
            //下面这行代码会导致任何问题吗?
            Console.WriteLine(longRunningTask.Result.Id);
            return user;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            return null;
        }
    }
    private static async Task DoSomethingAsync2()
    {
        try
        {
            var longRunningTask = Task.Factory.StartNew(() => LongRunner.LongRunnerInstance.DoSomethingThatTakesReallyLong());
            var user = await longRunningTask;
            Console.WriteLine(user.Id);
            return user;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            return null;
        }
    }
   public ActionResult Index()
   {
    //在主asp.net线程上运行的内容
    //独立运行的内容
    //目前不会使用此处返回的任务
    DoSomethingAsync1();
    //如果需要,在主asp.net线程上执行更多操作
    return View();             
   }

\nhttps://blog.stephencleary.com/2012/07/dont-block-on-async-code.html\nhttps://msdn.microsoft.com/en-us/magazine/jj991977.aspx\n谢谢

0
0 Comments

Does Task.Result have any impact when used after the await statement?

在上述代码中,我们可以看到在await语句之后使用了Task.Result。这会造成一些问题。在使用await关键字时,它会暂停当前方法的执行并等待被await的任务完成。而Task.Result是用于获取任务的结果的属性。如果在await之后使用Task.Result,可能会导致阻塞当前线程,直到任务完成,这与使用await的初衷相悖。

为了解决这个问题,我们应该遵循异步一致的规范。在这个规范中,我们应该尽可能地将异步调用延伸到整个调用链中,而不仅仅是在某个方法中使用await。在上述代码中,我们可以将Index方法修改为异步方法,并在其中调用DoSomethingAsync3方法。这样,整个调用链都会是异步的,避免了在await之后使用Task.Result的问题。

另外,需要注意的是,在控制器的Action方法中不应该使用ConfigureAwait(false),因为ASP.NET有一个同步上下文,并且需要它。如果在Action方法中使用ConfigureAwait(false),可能会导致一些意料之外的问题。

总结起来,为了避免在await之后使用Task.Result的问题,我们应该遵循异步一致的规范,将异步调用延伸到整个调用链中。此外,在控制器的Action方法中不应该使用ConfigureAwait(false)。这样可以确保代码的正确性和性能的最佳化。

0
0 Comments

在上述内容中,提出了一个关于Task.Result的问题:在使用await语句之后使用Task.Result会有什么影响?作者提到Task.Result会同步等待任务完成(与task.Wait()相同),然后返回结果(与await task相同)。由于任务已经完成,使用Result和await之间只有一个重要的区别:Result会将异常包装在AggregateException中。为了这个原因(也为了使代码更易于重构),作者建议尽可能使用await而不是Result。

然后,读者提出了一个关于Task.Result可能引发阻塞和死锁问题的疑问。作者回答说,由于它在线程池上下文中运行,所以在这种情况下不会引发问题。

接下来,作者提到了一些潜在的性能问题和注意事项。作者建议使用Task.Run而不是StartNew,不要在ASP.NET上执行fire-and-forget操作,不要暴露伪异步方法。还有使用Task.Run和GetAwaiter().GetResult()的示例代码,并指出这种方式会降低应用程序的可伸缩性。

最后,读者感谢作者的解答并表示会阅读作者关于Brownfield Async Development的文章。

,文章讨论了在使用await语句之后使用Task.Result的问题,并提供了解决方法和一些建议。

0