出让执行权:Task.Yield, Dispatcher.Yield - walterlv,毅仔的博客珠玉在前。同学们可以直接跳转过去看。

比较遗憾的是我没有在里面找到Task.Yield的合适的应用场景。关于Task.Yield的应用场景也是争论纷纷,可见这个东西必然很鸡肋。本文尝试了Task.Yield的几种使用场景,看看是否能够将代码变得更加优雅。

坐在MVP旁边狗尾续貂,诚惶诚恐。。


ReferenceSource里面看到Task.Yield方法会直接返回一个YieldAwaitable

如果你的代码是这么写

1552987762404

那么此时它将自身线程出让,然后从线程池中拿出一个线程继续执行后续的代码

那么问题来了,什么地方适合使用Task.Yield

1. 单独线程做大规模计算

1552988441349

你可能会想到使用Task.Yield来开启一个后台线程做大规模计算

1552988534203

但是实际上我们可以使用更加常见的Task.Run来替代。

大部分情况下上图的两种写法效果是一致的。

那么不一样的地方在哪里呢?第一种写法会在后续的计算中使用同步上下文,而第二种不会

当然如果你在开发WPF程序,而那个耗时计算又是在UI线程上,就可以选择第一种。

注意:Task.Yield没有ConfigureAwait方法,可见其设计目标就是同步上下文的工作情况

2.耗时UI操作,防卡顿

上一小节提出的一种操作场景就是通过Task.Yield对耗时UI操作进行“切片”,防止卡顿。

但是至少对于WPF程序来说,这里显然有更优的解决方案

1552995658282

或者

1552995724939

在UI线程Dispatcher.YieldTask.Yield是等价的,但是Dispatcher.Yield额外拥有精细化的优先级控制

3. 它真的很鸡肋,鸡肋到只剩下语法优化

研究之后我坚定了这个方法的鸡肋情况,绞尽脑汁能想到的就只有一些语法层面的简化

例如对于如下的循环中进行简写

1552996381863

1552996487299

这部分的代码简化后还是看着很清晰的

还有一种情况是在接口约束了返回值为Task的情况下,实现中没有异步时可以使用Task.Yield满足接口约束

1553062517635

当然你也可以使用Task.FromResult进行替代

1553062644070

不过这两者存在着是否进行线程切换的细微差别,大部分情况下,更少的线程切换(即Task.FromResult)是更优的

小结

Task.Yield可以快速便捷的出让线程的使用权,但是在实际应用上(至少是WPF)缺少较好的使用场景。

参考链接:


本文会经常更新,请阅读原文: https://xinyuehtx.github.io/post/%E4%BB%80%E4%B9%88%E6%98%AFtask.yield.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

知识共享许可协议 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名黄腾霄(包含链接: https://xinyuehtx.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系