递归任务控制流程

问题描述 投票:0回答:1

当我取消注释

await Task.Delay(1_000);
时,
foo.DoAsync
内的
Task.Run
Task.CompletedTask
,因为它等待
Task.Run
开销。这样就可以正常运行了。

当我评论

await Task.Delay(1_000);
时,Task.Run中的
foo.DoAsync
就是它本身。在调试模式下第一次命中断点 2 后,就不再命中断点 2。

internal class Foo
{
    public Task DoAsync { get; set; }

    public void Recursive()
    {
        // Breakpoint1
        Recursive();
    }
}
var foo = new Foo() { DoAsync = Task.CompletedTask };

//foo.Recursive();

Console.WriteLine($"Outer ThreadId: {Environment.CurrentManagedThreadId}");

var task = Task.Run(async () =>
{
    Console.WriteLine($"Inner ThreadId: {Environment.CurrentManagedThreadId}");
    // Breakpoint2
    await foo.DoAsync;
    Console.WriteLine("""
        ******
        ******
        ******
        done
        ******
        ******
        ******
        """);
});

await Task.Delay(1_000);

foo.DoAsync = task;

await foo.DoAsync;

我预计它会无限地击中断点 2,因为

foo.Recursive
将无限地击中断点 1,直到崩溃。首次命中断点 2 后控制流去往何处?

c# .net multithreading asynchronous
1个回答
0
投票

Task
创建的
Task.Run
仅运行一次。每次您
await
它都不会再次运行。这是一个常见的误解,在我学习异步编程时也让我措手不及。

await
语句是被动操作。它只是等待任务完成,除非任务已经完成,在这种情况下它会立即继续执行下一条语句。
await
不会影响任务的状态。如果任务尚未开始,则不会导致任务执行;如果任务已经完成,则不会导致任务重新启动。

© www.soinside.com 2019 - 2024. All rights reserved.