2

如果我在 C# 中调用RunSynchronously()a Task,这会导致在兔子洞中进一步异步调用同步运行吗?

假设我有一个名为UpdateAsync(). 在这个方法中,另一个异步调用被调用DoSomethingAsync(),在这个内部我们再次发现DoSomethingElseAsync(),调用RunSynchronously()'UpdateAsync()'会导致RunSynchronously()也间接被调用DoSomethingAsync()吗?

我的问题的原因: 我有一种情况,我“需要”在 -blockUpdateAsync()内调用异步方法 ( )catch并想知道调用它RunSynchronously()是否安全。文档非常清楚您不能awaitcatch-block 内。(严格来说,我可以在 -block 内使用布尔值catch并在 try-catch 之后调用UpdateAsync(),但这感觉很脏)。对双重问题感到抱歉,但正如您可能理解的那样,我不太知道如何表达它,并且对这个领域没有很好的理解。

编辑: 我不知道如何找出方法是否被异步调用。你将如何为此编写单元测试?是否可以以某种方式记录它?)

4

3 回答 3

6

我“需要”调用一个异步方法并想知道调用它RunSynchronously()是否安全

s有两种Task:code-based* Tasks(你可以使用Task构造函数或创建它们Task.Factory.StartNew())和 promise-style s(你可以通过使用或编写方法Task手动创建它们)。TaskCompletionSourceasync

唯一Task可以通过调用Start()或未启动RunSynchronously()基于代码的Tasks开始。由于 async 方法返回 promise 样式Task(或者可能已经开始基于代码的Tasks),因此调用RunSynchronously()它们是无效的并且会导致异常。

所以,要真正回答你的问题:你问的是不可能的,所以问它是否安全是没有意义的。


* 这不是官方名称,不知道有没有。

于 2013-04-17T11:12:34.603 回答
0

没有代码很难预测它将如何执行嵌套的异步方法。

您可以登录每个异步方法 Thread.CurrentThread.ManagedThreadId 属性并将 id 与您拥有的其他线程 ID 进行比较。当它们变化时,您的异步方法处于多线程执行中

或者尝试使用 Visual Studio 中的 Concurrency Visualizer,Analyze 菜单。使用 Task 类实例,即使使用 C#5 异步语法,也无法知道您是在并行执行还是在另一个线程执行。

于 2013-04-17T08:17:09.227 回答
-1

我想我会与@svick 的回答相矛盾,但我觉得 OP 问题是有效的,因为异步方法的“承诺”(使用 Svick 的术语)可以获得任务,但不能启动,因此允许执行Task.RunSynchronously().

    static void Main(string[] args)
    {
        ...
        //obtain a Task that's not started
        var t = new Task<int>((ob) => GetIntAsync((string)ob).Result, someString);
        ...
    }

    static async Task<int> GetIntAsync(string callerThreadId)
    {
       ...

话虽如此,答案是:不,这RunSynchronously()会影响您运行它的任务。如果调用链稍后包含更多异步调用,它们将异步运行。

我有一个小控制台应用程序正在对此进行建模,有人有兴趣看到它,但这个概念很容易重现 - 只需链接足够多的异步调用并在同步和异步运行最早的调用之间切换以查看不同的行为。

于 2013-04-17T19:31:14.653 回答