创建了以下控制台应用程序后,我有点困惑为什么它似乎同步运行而不是异步运行:
class Program
{
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var total = CreateMultipleTasks();
stopwatch.Stop();
Console.WriteLine("Total jobs done: {0} ms", total.Result);
Console.WriteLine("Jobs done in: {0} ms", stopwatch.ElapsedMilliseconds);
}
static async Task<int> CreateMultipleTasks()
{
var task1 = WaitForMeAsync(5000);
var task2 = WaitForMeAsync(3000);
var task3 = WaitForMeAsync(4000);
var val1 = await task1;
var val2 = await task2;
var val3 = await task3;
return val1 + val2 + val3;
}
static Task<int> WaitForMeAsync(int ms)
{
Thread.Sleep(ms);
return Task.FromResult(ms);
}
}
运行应用程序时,输出为:
完成的工作总数:12000毫秒
工作完成时间:12003毫秒
我原本期望像:
完成的工作总数:12000毫秒
工作完成时间:5003毫秒
这是因为当我使用Thread.Sleep方法时,它会停止进一步执行整个应用程序吗?或者我错过了一些重要的东西?
答案 0 :(得分:4)
即使您转换为使用Task.Run
或Task.Delay
作为其他答案建议,也应避免在Task.WaitAll
方法内的任何位置使用屏蔽async
,尽可能多。混合异步和同步代码通常是一个坏主意,它会增加冗余阻塞线程的数量并促进死锁。
相反,使用await Task.WhenAll
并将阻止等待移到顶层(例如,在这种情况下为Main
方法):
class Program
{
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var total = CreateMultipleTasks();
total.Wait();
stopwatch.Stop();
Console.WriteLine("Total jobs done: {0} ms", total.Result);
Console.WriteLine("Jobs done in: {0} ms", stopwatch.ElapsedMilliseconds);
}
static async Task<int> CreateMultipleTasks()
{
var task1 = Task.Run(() => WaitForMeAsync(5000));
var task2 = Task.Run(() => WaitForMeAsync(3000));
var task3 = Task.Run(() => WaitForMeAsync(4000));
await Task.WhenAll(new Task[] { task1, task2, task3 });
return task1.Result + task2.Result + task3.Result;
}
static int WaitForMeAsync(int ms)
{
// assume Thread.Sleep is a placeholder for a CPU-bound work item
Thread.Sleep(ms);
return ms;
}
}
在旁注上,查看Stephen Toub的"Should I expose asynchronous wrappers for synchronous methods?"和"Should I expose asynchronous wrappers for synchronous methods?"
答案 1 :(得分:1)
您的WaitForMeAsync方法只是一种假装为异步的简单同步方法。
你不执行任何异步操作,Sleep()只是阻塞线程。
为什么要延迟异步? (是的,你可以使用await Task.Delay(ms)
),需要更多的输入来帮助那里。
答案 2 :(得分:1)
您以同步方式运行任务。你可以这样做:
static async Task<int> CreateMultipleTasks()
{
var task1 = Task.Run<int>(() => WaitForMeAsync(5000));
var task2 = Task.Run<int>(() => WaitForMeAsync(3000));
var task3 = Task.Run<int>(() => WaitForMeAsync(4000));
Task.WaitAll(new Task[] { task1, task2, task3 });
return task1.Result + task2.Result + taks3.Result;
}
连续使用三个await
将不会并行运行任务。它只会在线程等待时释放线程(如果使用await Task.Delay(ms)
,因为Thread.Sleep(ms)
是阻塞操作),但当前执行不会继续task2
而task1
是&#34;睡觉&#34;。