8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

当多个 C# 任务在另一个任务完成时启动时会发生什么?

blogofsongs 2月前

75 0

假设我有以下代码:public async void Run(){ TaskCompletionSource t = new TaskCompletionSource(); Prepare(t.Task); await Task.Delay(1000); t.SetResult(); Console.

假设我有这样的代码:

public async void Run()
{
    TaskCompletionSource t = new TaskCompletionSource();
    Prepare(t.Task);
    await Task.Delay(1000);

    t.SetResult();
    Console.WriteLine("End");
}

public async void Prepare(Task task)
{
    await Run(task, "A");
    await Run(task, "B");
    await Run(task, "C");
    await Run(task, "D");
}

public async Task Run(Task requisite, string text)
{
    await requisite;
    Console.WriteLine(text);
}

时会发生什么 t.SetResult(); ?这是多线程吗?控制台中项目的顺序有任何保证吗?如果我有一个 List<> ,并且该 Run 方法会改变它,我需要担心多线程吗?

帖子版权声明 1、本帖标题:当多个 C# 任务在另一个任务完成时启动时会发生什么?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由blogofsongs在本站《multithreading》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 当你写了一个简单的 await 语句时;

    await requisite;
    

    C# 编译器将您的方法移至单独的类,并将该“简单”转换 await 为等效的内容;

    private Task requisite;
    private int state = 0;
    private void MoveNext()
    {
        switch (state)
        {
            case 0:
                var awaiter = requisite.GetAwaiter();
                if (!awaiter.IsCompleted)
                {
                    state = 1;
                    awaiter.OnCompleted(MoveNext);
                    return;
                }
                goto case 1;
            case 1:
                // resume execution here when the task is complete
                break;
        }
    }
    

    如您所见,如果任务已完成,您的代码将同步继续。如果任务未完成,则会注册一个回调,以便稍后继续执行。

    每个等待程序的具体实现可能完全不同。例如, Task.Yield 将返回一个永远不会完成的等待程序。强制继续在线程池上执行。

    大多数任务类型以及示例中的所有任务都会在 .SetResult 调用时同步调用每个延续方法。

    回到你的具体例子;

    public async void Prepare(Task task)
    {
        await Run(task, "A");
        await Run(task, "B");
        await Run(task, "C");
        await Run(task, "D");
    }
    

    第一次调用时, Run 任务未完成,因此 Run 将注册一个延续 Action 中的 await 第一个 Prepare 也将看到返回的任务未完成。尽管该方法 void 如此,但不会返回另一个未完成的任务。

    当您在延迟后恢复并调用 时 t.SetResult(); 将首先调用 Run 已注册的用于恢复 的延续方法 Run 方法完成时,而不是返回, .SetResult 将在未完成的任务上调用 ,从而立即调用 的延续 Prepare 。所有这些都将在同一线程中发生,在 t.SetResult 返回之前。

    Run 中放置断点 Prepare 并检查调用堆栈,您会看到线程堆栈与您通常预期的相反。每个返回 async 在堆栈中 SetResult 调用

返回
作者最近主题: