代码之家  ›  专栏  ›  技术社区  ›  ca9163d9

等待一些函数并继续运行一些代码,同时等待任务。什么时候?

  •  0
  • ca9163d9  · 技术社区  · 7 年前

    有以下功能。

    async Task<int> T1() { Console.WriteLine("T1"); return await Task.FromResult(1); }
    async Task<string> T2() { Console.WriteLine("T2"); return await Task.FromResult("T2"); }
    async Task<char> T3() { await Task.Delay(2000); Console.WriteLine("T3"); return await Task.FromResult('A'); }
    async Task<string> T4() { Console.WriteLine("T4"); return await Task.FromResult("T4"); }
    
    // U1, U2, U3, and U4 need to be run right after T1, T2, T3, and T4 respectively
    void U1() { System.Threading.Thread.Sleep(1000); Console.WriteLine($"After T1"); }
    void U2() { System.Threading.Thread.Sleep(4000); Console.WriteLine($"After T2"); }
    void U3() { System.Threading.Thread.Sleep(1000); Console.WriteLine($"After T3"); }
    void U4() { System.Threading.Thread.Sleep(1000); Console.WriteLine($"After T4"); }
    
    // TAll() needs to be run as soon as T1, T2, T3, and T4 finished.
    void TAll() { Console.WriteLine("To be run after T1, T2, T3, T4"); }
    
    // All() runs after all functions are done.
    void All() { Console.WriteLine("To be run after U1, U2, U3, U4"); }
    

    但是,以下调用

    var t1 = T1().ContinueWith(_ => U1());
    var t2 = T2().ContinueWith(_ => U2());
    var t3 = T3().ContinueWith(_ => U3());
    var t4 = T4().ContinueWith(_ => U4());
    await Task.WhenAll(t1, t2, t3, t4);
    TAll();
    
    All();
    

    退货

    T1
    T2
    T4
    After T1
    After T4
    T3
    After T3
    After T2
    To be run after T1, T2, T3, T4
    To be run after U1, U2, U3, U4
    

    预期的输出顺序是

    T1
    T2
    T4
    After T1
    After T4
    T3
    To be run after T1, T2, T3, T4
    After T3
    After T2
    To be run after U1, U2, U3, U4
    
    2 回复  |  直到 7 年前
        1
  •  4
  •   Stephen Cleary    7 年前

    你应该 use async and await rather than ContinueWith . 在您的情况下,添加新的 异步

    var t1 = T1();
    var u1 = InvokeU1(t1);
    var t2 = T2();
    var u2 = InvokeU2(t2);
    var t3 = T3();
    var u3 = InvokeU3(t3);
    var t4 = T4();
    var u4 = InvokeU4(t4);
    
    await Task.WhenAll(t1, t2, t3, t4);
    TAll();
    
    await Task.WhenAll(u1, u2, u3, u4);
    All();
    
    async Task InvokeU1(Task task) { await task; U1(); }
    async Task InvokeU2(Task task) { await task; U2(); }
    async Task InvokeU3(Task task) { await task; U3(); }
    async Task InvokeU4(Task task) { await task; U4(); }
    
        2
  •  3
  •   Johnny    7 年前

    任务的延续实际上就是任务。在你的例子中,你正在等待续集,所以 “被追杀…” 将在所有目标任务及其所有延续完成时记录。

    考虑一下这个:

    //target tasks
    var t1 = T1();
    var t2 = T2();
    var t3 = T3();
    var t4 = T4();
    
    //continuations
    var c1 = t1.ContinueWith(_ => U1());
    var c2 = t2.ContinueWith(_ => U2());
    var c3 = t3.ContinueWith(_ => U3());
    var c4 = t4.ContinueWith(_ => U4());
    
    await Task.WhenAll(t1, t2, t3, t4);
    TAll();
    
    await Task.WhenAll(c1, c2, c3, c4);
    All();
    

    更新

    斯蒂芬补充了一个关于 ContinueWith 我鼓励你使用它。不管有多危险 继续

        3
  •  0
  •   Asif    7 年前

    既然你有 await Task.WhenAll(t1, t2, t3, t4);

    To be run after T1, T2, T3, T4
    To be run after U1, U2, U3, U4