4

假设我要编写一个异步方法 M。我不知道会使用什么样的同步上下文(UI、ASP.NET、控制台应用程序等)来调用它。我想让该方法尽可能易于使用。这意味着任何人都应该能够通过访问返回任务的 Result 成员来同步调用它。

public async Task<int> M()
{
    // lot's of calling of helper methods including awaits, etc.
    // helper methods not owned by me
    // ...

    return 42;
}


// this should be safe to do from any synchronization context
int result = M().Result; // Synchronously wait

问题是方法 M 的调用者的同步上下文被泄露给了 M 的被调用者。如果他们中的任何一个想要在传入的同步上下文上继续,那么它可能会死锁(例如,当使用 UI 同步上下文时)。

在调用 M 时忘记同步上下文的一种解决方案是将 M 的内容包装在 Task.Run 中。但是,这将强制线程跳转,包括在 M 中的所有任务都已完成并且所有内容都可以在同一个线程上同步运行而无需上下文切换的情况下。有没有更好的解决方案来忘记线程的同步上下文?或者我是否遗漏了一些东西,这会使这个问题变得无关紧要?

4

1 回答 1

3

我想让该方法尽可能易于使用。这意味着任何人都应该能够通过访问返回任务的 Result 成员来同步调用它。

没有简单的方法可以为异步方法创建同步包装器。最好让异步方法异步。

可以使用ConfigureAwait(continueOnCapturedContext: false)丢弃上下文,但它不会比Task.Run您的情况更好,因为您无法更改M调用的方法。

于 2013-05-30T11:14:37.077 回答