关于异步,为毛Task.Wait()一执行就停止响应

wShineboy 2018-07-13 11:32:13
先看看这段小程序,不过是利用异步调用显示一系列可变化的数据。


Console.WriteLine("开始");
Random Rnd = new Random(Environment.TickCount);
for (int Ii = 0; Ii <= 5; Ii++)
{
Task TskXy = new Task(() =>
{
float Xx = (float)Environment.TickCount / 117f;
float Yy = (float)Rnd.NextDouble() * 99f;
this.Invoke(new IvkSetXy(SetXY), new object[3] { Ii, Xx, Yy });//BeginInvoke
});
TskXy.Start();

Task Cwh = TskXy.ContinueWith(t =>
{
System.Threading.Thread.Sleep(50);
Console.WriteLine(Ii);
});

//TskXy.Wait();//后续加上这句就会使程序停止响应
//TskXy.Wait();//后续加上这句就会使程序停止响应
//TskXy.Wait();//后续加上这句就会使程序停止响应

}
Console.WriteLine("结束");


程序输出结果:
开始
结束
6
6
6
6
6
6
很显然,异步处理尚未完成,循环已经结束了。这个道理不难理解,所以加入“Wait()”方法来等待异步处理完成,但这个东西加上后程序就会停止响应——只能到VS中去结束运行。

请教各位,这个Wait真的是个坑吗?
...全文
1374 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
wShineboy 2018-07-27
  • 打赏
  • 举报
回复
楼上诸君所言极是,此乃同步任务,万不该以“异步”为之也。
维秀斯丢丢 2018-07-17
  • 打赏
  • 举报
回复
引用 30 楼 twotuli_software 的回复:
既然要异步去做,又要等待它做完,那干嘛不同步做呢? 别乱用异步啊,兄弟。

你开5个任务,顶多是想程序执行快一点 ,task.waitAll是不会有问题的。
维秀斯丢丢 2018-07-17
  • 打赏
  • 举报
回复
既然要异步去做,又要等待它做完,那干嘛不同步做呢? 别乱用异步啊,兄弟。
会思考的草 2018-07-17
  • 打赏
  • 举报
回复
Task.Wait就是阻塞的,Task.Wait会一直卡在那直到Task结束。
m0_37885684 2018-07-16
  • 打赏
  • 举报
回复
好厉害,值得学习
  • 打赏
  • 举报
回复
如果是“待下一帧数据的获取时间达到后再继续”,那么这就更加是事件驱动基本概念,有了“数据到达”的事件的驱动才去读取和显示,没有数据到达时就不占用任何线程(更不阻塞 UI 主线程)。

你说的一大堆理由,是因为你不理解异步,所以根本无法从技术角度去深入下去去设计了。
  • 打赏
  • 举报
回复
以异步而不是同步的思路来实现这样的需求,比如说拿出 10分钟前的数据画一个图,然后“等待1分钟”再拿出9分钟前的数据更新图,然后“等待一分钟”再拿出8分钟前的数据更新图.........你看来不懂言这个描述中的异步的概念。异步的等待就不是什么阻塞,连 js 程序员都懂的写个
setTimeout( func, 60000);
的语句来定时执行连续流程,你怎么就连异步基本概念反反复复都不懂呢?
wShineboy 2018-07-16
  • 打赏
  • 举报
回复
连需求都没弄清楚,就直接编程。很快制造出一堆高效而规范的代码……

设计目标:重现一组数据的变化过程——显示实际数值并绘制曲线来展现变化趋势。
分析:电脑处理速度 > 数值变化频率 > 肉眼可接受速度。
结果:编程的要点不在于速度,而是在正确的时间显示正确的数值,并使用Chart便于工作人员观察和分析数据变化。

所以要在显示数值后停顿一下,待下一帧数据的获取时间达到后再继续……
为了确保曲线不失真,应该添加足够多的点到Chart,而考虑到人眼接受能力,曲线刷新速度可适当放慢(每秒3-5次即可,这样可节约时间做其它处理) 而异步/多线程,只是为了不影响UI的响应。

有空看看9楼再说吧。
xiaoxiangqing 2018-07-16
  • 打赏
  • 举报
回复
Wait()是同步,await 才是异步
sdfgrtyu 2018-07-16
  • 打赏
  • 举报
回复
楼主厉害!!!,,
足球中国 2018-07-14
  • 打赏
  • 举报
回复
后台线程处理数据,与GUI更新数据。两个中间是数据。不要把两个直接扯到一起。比如你的 this.Invoke(
两个独立分开,你会发现程序会更简单。而且高效。
金钟塔 2018-07-14
  • 打赏
  • 举报
回复
楼主厉害!!!程序简单。而且高效。
Zzz薯 2018-07-14
  • 打赏
  • 举报
回复
楼主厉害!!!
  • 打赏
  • 举报
回复
“Sleep阻塞、动不动就是一个大While 循环”等等概念充斥大脑,恰好说明了不懂异步编程。
  • 打赏
  • 举报
回复
引用 14 楼 zhoujg751206 的回复:
为什要wait加上那个起什么作用。如果延迟用sleep啊


lz 不是要延迟,实际上是要顺序操作。

异步编程是完全可以顺序的,比如说异步操作的目的是等到某个事件发生时才执行委托、而委托中继续处理第二阶段工作。

这在 js 程序员都是非常简单的事情,因为 ajax 的闻名使得他们懂得了什么叫做回调函数。可是 .net 程序员却不懂,这就是基本编程入门教育的失败。看上去 .net、c# 的课程很多,其实对于比小伎俩的设计模式更加基本的设计模式,则讲的比较少,缺乏基础知识。
  • 打赏
  • 举报
回复
我再次给你强调一遍,你写的

引用 楼主 wShineboy 的回复:
这个道理不难理解,所以加入“Wait()”方法来等待异步处理完成
这个是绝对稀里糊涂的概念。你仔细想想我举的”应聘“的例子就明白,异步编程必须是事件回调、在未知的时间你注册的委托被回调的机制的。如果你想阻塞,那你就不懂异步。

所以你要彻底改变自己的编程设计思路,才能理解异步。
  • 打赏
  • 举报
回复
在 Task 编程模式中,异步是什么?异步是类似
await Tsk;
var result = await Tsk1;
这类代码,这才叫做异步。

而写
Tsk.Wait();
var result = Tsk1.Result;
这类代码叫做同步,叫做拿着 Task 当作标题党——其实是只会同步编程。
  • 打赏
  • 举报
回复
先了解下主线程子线程吧
  • 打赏
  • 举报
回复
比如说你去应聘,人家如果让你上班的话就会给你打电话通知。这就叫做异步。

现在你说“为了等待人家打电话”,所以你就捆住人家手脚、阻塞人家工作“,让人家什么都不干,这样你就能等待来人家的电话了吗?显然这种 Wait 代码根本不懂异步啦。
  • 打赏
  • 举报
回复
引用 楼主 wShineboy 的回复:
很显然,异步处理尚未完成,循环已经结束了。这个道理不难理解,所以加入“Wait()”方法来等待异步处理完成


你看看来是还完全没有理解异步编程机制。

异步处理完,回调(或者说抛出事件)原本注册的委托。你在所谓的“异步”中写同步阻塞代码,这显然是“此地无银三百两”,根本不是异步设计。
加载更多回复(11)

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧