尽管async
和await
已经出现了一段时间,并且由于长时间使用C#dev,我仍然很难理解它们的工作原理以及何时使用它们。所以我正在写一些测试代码!
我正在尝试 asynchronoulsy 从主主题调用任务A ,然后调用任务A 任务A完成后,然后调用任务C 。
在伪代码中,这将是:
RunAsync(TaskA())
.Then(TaskB())
.Then(TaskC());
我写了以下示例,但是没有按照我的预期行事。相反或运行A然后运行B然后运行A,它运行A,然后B 和 C运行在并行。
C#片段如下(详情如下):
Task
.Run(async () => await LongTaskAsync("A"))
.ContinueWith(async (taskA) => await LongTaskAsync("B"))
.ContinueWith(async (taskB) => await LongTaskAsync("C"));
我打印出了线程ID,我有:
以下是代码:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace AsyncTests
{
class Program
{
private static DateTime _start;
static void Main(string[] args)
{
_start = DateTime.Now;
Log("======= Main thread starts ======");
Log($"Main thread ID : {Thread.CurrentThread.ManagedThreadId}");
// Start a stack of aynchronous calls
Task
.Run(async () => await LongTaskAsync("A"))
.ContinueWith(async (taskA) => await LongTaskAsync("B"))
.ContinueWith(async (taskB) => await LongTaskAsync("C"));
Log("====== Main thread returns ======");
Console.ReadKey();
}
static async Task LongTaskAsync(string name)
{
Log($"Long async task {name} starts");
Log($"{name} thread ID : {Thread.CurrentThread.ManagedThreadId}");
for(var i = 1 ; i <= 5 ; i++)
{
Log($"Task {name} says {i}");
await Task.Delay(1000);
}
Log($"Long async task {name} returns");
}
static void Log(string text)
{
var elpased = (int)(DateTime.Now - _start).TotalMilliseconds;
Console.WriteLine($"[+{elpased.ToString().PadLeft(4,'0')}] {text}");
}
}
}
控制台输出:
[+0003] ======= Main thread starts ======
[+0009] Main thread ID : 1
[+0016] ====== Main thread returns ======
[+0022] Long async task A starts
[+0024] A thread ID : 3
[+0024] Task A says 1
[+1028] Task A says 2
[+2029] Task A says 3
[+3030] Task A says 4
[+4031] Task A says 5
[+5032] Long async task A returns
[+5034] Long async task B starts
[+5034] B thread ID : 4
[+5034] Task B says 1
[+5035] Long async task C starts
[+5036] C thread ID : 4
[+5036] Task C says 1
[+6036] Task C says 2
[+6036] Task B says 2
[+7037] Task C says 3
[+7037] Task B says 3
[+8038] Task B says 4
[+8038] Task C says 4
[+9039] Task C says 5
[+9039] Task B says 5
[+10040] Long async task C returns
[+10040] Long async task B returns
答案 0 :(得分:2)
如果您希望按顺序拨打电话,只需await
他们:
Task.Run(async () =>
{
await LongTaskAsync("A");
await LongTaskAsync("B");
await LongTaskAsync("C");
});
示例输出:
[+0000] ======= Main thread starts ======
[+0001] Main thread ID : 1
[+0015] ====== Main thread returns ======
[+0020] Long async task A starts
[+0020] A thread ID : 3
[+0020] Task A says 1
[+1021] Task A says 2
[+2021] Task A says 3
[+3022] Task A says 4
[+4022] Task A says 5
[+5024] Long async task A returns
[+5024] Long async task B starts
[+5024] B thread ID : 4
[+5024] Task B says 1
[+6025] Task B says 2
[+7026] Task B says 3
[+8026] Task B says 4
[+9027] Task B says 5
[+10028] Long async task B returns
[+10028] Long async task C starts
[+10028] C thread ID : 3
[+10028] Task C says 1
[+11029] Task C says 2
[+12029] Task C says 3
[+13030] Task C says 4
[+14032] Task C says 5
[+15032] Long async task C returns
但是,如果任何任务失败(由于await
),上述代码将失败。如果您希望这些始终运行,您将需要一个更丑陋的方法:
Task.Run(() =>
{
LongTaskAsync("A").ContinueWith((taskA) =>
{
LongTaskAsync("B").ContinueWith((taskB) => LongTaskAsync("C"));
});
});
这与您的实际代码之间的区别在于您为继续工作分配的任务。