c# - TaskCompletionSource 执行缓慢
问题描述
通过在同步方法中循环多个TaskCompletionSource实例,超过5个程序执行起来会变慢,但是在异步方法中就没有这个问题了。
这是有问题的代码 使用同步方式,执行变慢,1秒左右创建一个
Parallel.For(1, 100, (index) =>
{
System.Console.WriteLine("start:");
var t = new TaskCompletionSource<string>();
count++;
System.Console.WriteLine("end:" + count + "\n");
t.Task.Wait();
System.Console.WriteLine("ended:");
});
这是没有问题的代码,执行非常快
Parallel.For(1, 100, async (index) =>
{
System.Console.WriteLine("start:");
var t = new TaskCompletionSource<string>();
count++;
System.Console.WriteLine("end:" + count + "\n");
await t.Task;
System.Console.WriteLine("ended:");
});
解决方案
你对 有一些误解Parallel.For()
。
首先,Parallel.For()
不是为异步任务设计的。许多帖子中已经提到过:
想象一下,在厨房里,你有 5 个厨师(线程),Parallel.For()
正在将每个待处理的菜一个一个地分配给每个厨师,直截了当。但是async-await
,正在分配“承诺我会做一道菜的协议”来做饭,这是一个约会,只有线程启动它并“完成”这个过程。
这就是为什么您在async-await
示例中得到非常快速的响应的原因。但是这一行:
System.Console.WriteLine("ended:");
不打印。当工作线程遇到 时await
,此任务结束。
让我们简化您正在使用的示例,这不是测试andTaskCompletionSource
之间差异的好示例。async-await
Parallel.For()
//Async
Parallel.For(1, 100, async (index) =>
{
System.Console.WriteLine("start:" + index);
await Task.Delay(1000);
System.Console.WriteLine("ended:" + index);
});
//Task.Delay(2000).Wait();
Async-await
ended: index
在这种情况下永远不会打印。尝试Task.Delay(2000).Wait();
在末尾添加一行,您可以注意到ended:index
最终打印出来了。
尝试减少1000
延迟1
,它可能会打印一些ended
但它不能保证,Parallel.for
这意味着你的任务根本不会在Parallel.for()
线程内等待,它由另一个线程持有async-await
。
//Sync
Parallel.For(1, 100, (index) =>
{
System.Console.WriteLine("start:" + index);
Task.Delay(1000).Wait();
System.Console.WriteLine("ended:" + index);
});
并行怎么样,是的,它很“慢”,启动线程和任务调度程序需要成本。但这确实是在告诉您任务在程序结束之前完成。
推荐阅读
- django - Django多客户端部署解决方案
- database - 函数和光标帮助 ORACLE PL/SQL
- postgresql - 带有 ORDER BY 和 LIMIT 的 Postgres UNION
- database - 如何在 DolphinDB 中设置数据保留时间?
- python - 如何从 Json Url 中获取价值?
- kubernetes - 有时缺少desiredContainers
- java - 即使在系统关闭后,Oracle 活动和非活动会话仍然存在
- postgresql - 行或列的大小是否会影响 Postgresql 中的聚合查询?
- powershell - 为什么 powershell2 iex (Invoke-Expression) 打开一个新的控制台?
- syntax - 使用计算字段计算每个用户的事件频率