【问题标题】:Neither GetAwaiter().GetResult() nor .Result worked for me but Task.Run(await ()=> nameOfMethodTobeCalled()).Result working. I didn't understand?GetAwaiter().GetResult() 和 .Result 都不适合我,但 Task.Run(await ()=> nameOfMethodTobeCalled()).Result 工作。我没看懂?
【发布时间】:2020-05-10 03:08:31
【问题描述】:

在我的 asp.net 应用程序中,我正在调用我添加到我的应用程序中的一个 nuget 包的一些异步方法。现在我有一个同步方法,我需要在其中调用我添加的 .dll 的异步方法。因此,为此我调用了这些方法并检索我使用的结果

var value = myDllClient.MyMethod().GetAwaiter().GetResult();和
var value = myDllClient.MyMethod().Result;,

但是这些都不适合我,但是线程进入了永无止境的过程。我从来没有收到任何东西 所以我用

var value = Task.Run(async ()=> await myDllClient.MyMethod()).Result;

出奇地工作正常。 我不知道它是如何工作的? 谁能帮我理解这个奥秘?

提前致谢

【问题讨论】:

标签: c# multithreading dll async-await task-parallel-library


【解决方案1】:

因此我调用了这些方法并检索我使用的结果

更好的解决方案是使用awaitallow the asynchrony to grow naturally through the code base。如果您确实必须进行异步同步,那么direct blocking like that may cause deadlocks

await captures a context by default,在您的情况下,MyMethod 内部的await 正在捕获ASP.NET request context,它存在于pre-Core 版本的 ASP.NET 上。然后,调用代码通过调用GetResult()/Result 阻塞该请求上下文中的线程。稍后,当await 准备好继续时,它将MyMethod 的其余部分调度到该上下文。但它永远不会运行,因为在该上下文中有一个线程阻塞等待MyMethod 完成。

Task.Run 没有死锁的原因是MyMethod 使用线程池上下文而不是 ASP.NET 请求上下文。这是进行异步同步的"thread pool hack" 方法。但是,Task.Run is not recommended on ASP.NET;如果可能,将代码更改为使用await

【讨论】:

  • 不可能一路异步更改代码,因为我在 asp.net 上开发了一项非常古老的 microsoft build 服务。现在我需要实现他们的新 dll 之一。如果 Task.Run 不是首选,那么我应该使用什么,因为我无法将其全部转换为等待?感谢您以上精彩的指导@Stephen Cleary..
  • @MukeemAhmed:在这种情况下,我会使用类似this NoContext method
【解决方案2】:

通过将您的调用包装在 Task.Run 中,您将该代码与 ASP.NET 的 SynchronizationContext 隔离开来,因此您的代码不会死锁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 1970-01-01
    • 1970-01-01
    • 2019-02-05
    • 1970-01-01
    • 1970-01-01
    • 2015-03-15
    相关资源
    最近更新 更多