出让执行权:Task.Yield, Dispatcher.Yield

一个耗时的任务,可以通过 Task.Yield 或者 Dispatcher.Yield 来中断以便分割成多个小的任务片段执行。

Yield 这个词很有意思,叫做“屈服”“放弃”“让步”,字面意义上是让出当前任务的执行权,转而让其他任务可以插入执行。Task、Dispatcher、Thread 都有 Yield() 方法,看起来都可以让出当前任务的执行权。



本文内容
  • Dispatcher.Yield

    • 需要注意

  • Task.Yield


如果在阅读中发现对本文涉及到的一些概念不太明白,可以阅读:

  • 深入了解 WPF Dispatcher 的工作原理(Invoke/InvokeAsync 部分)

  • 深入了解 WPF Dispatcher 的工作原理(PushFrame 部分)


如果一个方法的实现比较耗时,为了不影响 UI 的响应,你会选择用什么方法呢?我之前介绍过的 Invoke 和 InvokeAsync 可以解决,将后续耗时的任务分割成一个个小的片段以低于用户输入和渲染的优先级执行。

Dispatcher.Yield 也可以,其行为更加类似于 Dispatcher.InvokeAsync(即采用 Dispatcher 调度的方式,事实上后面会说到其实就是调用了 InvokeAsync),而非 Dispatcher.Invoke(即采用 PushFrame 新开消息循环的方式)。

使用时需要 await:

foreach(var item in collection)
{
DoWorkWhichWillTakeHalfASecond();
await Dispatcher.Yield();
}

这样,这个 foreach 将在每遍历到一个集合项的时候中断一次,让 UI 能够响应用户的交互输入和渲染。

Yield 方法可以传入一个优先级参数,指示继续执行后续任务的优先级。默认是 DispatcherPriority.Background,低于用户输入 DispatcherPriority.Input、 UI 逻辑 DispatcherPriority.Loaded 和渲染 DispatcherPriority.Render。

Dispatcher.Yield 是如何做到出让执行权的呢?

查看源码,发现 DispatcherYield 的返回值是 DispatcherPriorityAwaiter,而它的 OnCompleted 方法是这样的:

public void OnCompleted(Action continuation)
{
if(_dispatcher == null)
throw new InvalidOperationException(SR.Get(SRID.DispatcherPriorityAwaiterInvalid));
_dispatcher.InvokeAsync(continuation, _priority);
}

所以,其实真的就是 InvokeAsync。如果希望了解为何是 OnCompleted 方法,可以阅读 【C#】【多线程】【05-使用C#6.0】08-自定义awaitable类型 - L.M。

Dispatcher.Yield 是 Dispatcher 类型的静态方法,而不是像 InvokeAsync一样是实例方法。不过 C# 有一个神奇的特性——静态方法和实例方法可以在同一上下文中调用,而不用担心产生歧义。

例如:

using System.Windows.Threading;

class Demo : DispatcherObject
{
void Test()
{
// 调用静态方法 Yield。
await Dispatcher.Yield();
// 调用实例方法 InvokeAsync。
await Dispatcher.InvokeAsync(() => { });
}
}

注意需要引用命名空间 System.Windows.Threading。


拿前面 Dispatcher.Yield 的例子,我们换成 Task.Yield:

foreach(var item in collection)
{
DoWorkWhichWillTakeHalfASecond();
await Task.Yield();
}

效果与 Dispatcher.Yield(DispatcherPriority.Normal) 是一样的。因为 Task 调度回到线程上下文靠的是 SynchronizationContext,WPF UI 线程的 SynchronizationContext 被设置为了 DispatcherSynchronizationContext,使用 Dispatcher 调度;而 DispatcherSynchronizationContext 构造时传入的优先级默认是 Normal,WPF 并没有特殊传入一个别的值,所以 WPF UI 线程上使用 Task.Yield() 出让执行权后,恢复时使用的是 Normal 优先级,相当于 Dispatcher.Yield(DispatcherPriority.Normal)。

希望了解 Dispatcher 和 SynchronizationContext 的区别可以阅读 c# - Difference between Synchronization Context and Dispatcher - Stack Overflow。

DispatcherSynchronizationContext 执行 await 后续任务的上下文代码:

/// <summary>
/// Asynchronously invoke the callback in the SynchronizationContext.
/// </summary>
public override void Post(SendOrPostCallback d, Object state)
{
// Call BeginInvoke with the cached priority. Note that BeginInvoke
// preserves the behavior of passing exceptions to
// Dispatcher.UnhandledException unlike InvokeAsync. This is
// desireable because there is no way to await the call to Post, so
// exceptions are hard to observe.
_dispatcher.BeginInvoke(_priority, d, state);
}

既然是 Normal 优先级,那么在 UI 线程上的效果自然不如 Dispatcher.Yield。但是,Task.Yield 适用于任何线程,因为 SynchronizationContext 本身是与 Dispatcher 无关的,适用于任何线程。这样,于如果一个 Task 内部的任务太耗时,用 Task.Yield 则可以做到将此任务分成很多个片段执行。

如果觉得 Task.Yield() 的用途难以理解,可以参考 dudu 的博客 终于明白了 C# 中 Task.Yield 的用途 - dudu - 博客园。


参考资料

  • c# - Task.Yield - real usages? - Stack Overflow

  • Task.Yield Method (System.Threading.Tasks)

  • c# - Difference between Synchronization Context and Dispatcher - Stack Overflow

原文地址:https://walterlv.com/post/yield-in-task-dispatcher.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 
640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/315742.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HDU4372 Count the Buildings

HDU4372 Count the Buildings 题目描述 Solution 思路很妙。 考虑从最高的一个楼房将序列分开&#xff0c;左边可以看到FFF个&#xff0c;右边可以看到BBB个&#xff0c;一个楼房可以被看到&#xff0c;则一定是其之前没有比它高的楼房&#xff0c;其之后有若干个比它矮的楼…

VS Code 即将迎来再一次的 logo 更新!已可在 Insiders 版本尝鲜

为什么要说“再一次”&#xff1f; 相信 VS Code 的老用户都还记得两年前的 logo 更新风波吧。当时 VS Code 改了新 logo 之后&#xff0c;VS Code 的用户们一片哀嚎&#xff0c;纷纷觉得新 logo 太丑&#xff0c;在 GitHub 和各种社交媒体上各种吐槽&#xff01;不过幸运的是&…

CF961G Partitions

CF961G Partitions 题目描述 Solution 推式子&#xff1a; AnsAnsAns ∑wi∑s0n(n−1s−1){n−sk−1}\sum w_i\sum_{s0}^n\left ( \begin{aligned} n-1 \\ s-1 \end{aligned} \right ) \left\{ \begin{aligned} n-s \\ k-1 \end{aligned} \right\}∑wi​∑s0n​(n−1s−1​)…

从零开始在 Windows 上部署 .NET Core 到 Kubernetes

本章节所有代码已上传至&#xff1a;https://github.com/Seanwong933/.NET-Core-on-Kubernetes文末附有本人遇到过的 Docker 和 k8s 的故障排除。本文目标&#xff1a;带领大家在 Kubernetes 上部署一个 .NET Core Api 的单节点集群。后续文章会帮助大家继续深入。安装 Kuberne…

bzoj5093: [Lydsy1711月赛]图的价值

bzoj5093: [Lydsy1711月赛]图的价值 题目描述 Solution 考虑每一个点的贡献&#xff0c;枚举它的度数。 Ansn∗2(n−12)∑i1n−1(n−1i)∗ikAnsn*2^{\tbinom{n-1}{2}}\sum_{i1}^{n-1} \left( \begin{aligned} n-1 \\ i\;\;\; \end{aligned} \right)*i^kAnsn∗2(2n−1​)i1∑…

.NET Core微服务 权限系统+工作流(一)权限系统

一、前言实际上权限系统老早之前我就在一直开发&#xff0c;大概在刚毕业没多久就想一个人写一个系统&#xff0c;断断续续一直坚持到现在&#xff0c;毕竟自己亲动手自写的系统才有收获&#xff0c;本篇仅介绍权限。小小系统上不了台面&#xff0c;望各位大神勿喷。二、系统介…

bzoj#3456. 城市规划

bzoj#3456. 城市规划 题目描述 Solution 用组合意义推很简单。 iii个点的简单无向图个数为2(i2)2^{\tbinom{i}{2}}2(2i​)个。 则其EGFEGFEGF为 G(x)∑i>02(n2)i!xiG(x)\sum_{i>0}\frac{2^{\tbinom{n}{2}}}{i!}x^i G(x)i>0∑​i!2(2n​)​xi 令iii个点的简单无向连…

iNeuOS云操作系统,.NET Core全系打造

一.演示地址演示地址&#xff1a; 进入iNeuOS系统。&#xff08;建议使用chrome浏览器&#xff09;http://192.144.173.38:8081/login.html测试名称&#xff1a;admin测试密码&#xff1a;admin下载《iNeuOS云操作系统演示应用手册》 链接&#xff1a;https://pan.baidu.co…

译 | 你到底有多精通 C# ?

点击上方蓝字关注“汪宇杰博客”文&#xff1a;Damir Arh译&#xff1a;Edi Wang即使是具有良好 C# 技能的开发人员有时候也会编写可能会出现意外行为的代码。本文介绍了属于该类别的几个 C# 代码片段&#xff0c;并解释了令人惊讶的行为背后的原因。Null 值我们都知道&#xf…

uoj#422. 【集训队作业2018】小Z的礼物

uoj#422. 【集训队作业2018】小Z的礼物 题目描述 Solution 所有礼物全部取到的方案数并不好求&#xff0c;因此我们考虑min−maxmin-maxmin−max容斥&#xff0c;转化为第一次取到集合中某一个的期望时间。 令pn∗(m−1)m∗(n−1)pn*(m-1)m*(n-1)pn∗(m−1)m∗(n−1)表示有…

[开源] FreeSql AOP 功能模块 - FreeSql

FreeSql 是一个功能强大的 .NETStandard 库&#xff0c;用于对象关系映射程序(O/RM)&#xff0c;支持 .NETCore 2.1 或 .NETFramework 4.6.1&#xff08;QQ群&#xff1a;4336577&#xff09;。据了解&#xff0c;用户使用很少问问题&#xff0c;编码过程中&#xff0c;因业务阻…

Atcoder ARC062F - AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer

Atcoder ARC062F - AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer 题目描述 简要题意&#xff1a;给定一个有标号的无向图&#xff0c;你可以给每条边染上KKK种颜色之一&#xff0c;求本质不同的图的染色方案&#xff08;两个图本质不同定义为不能通过若干次环…

各大主流K8S服务全方位能力比对

大家好&#xff0c;趁打开流量主的东风&#xff0c;特此贡献一篇长文&#xff0c;分析一下目前国内国外几大著名云厂商的kubernetes服务&#xff0c;以飨诸君。文起之前&#xff0c;先聊态度。 我本人是十分看好k8s的发展的&#xff0c;为何&#xff1f; 理因古往今来&#xff…

CF868F Yet Another Minimization Problem

CF868F Yet Another Minimization Problem 题目描述 Solution 一开始可以很容易地写出一个dpdpdp式子&#xff1a; 设fi,jf_{i,j}fi,j​表示前iii个数分成jjj段的最小代价&#xff0c;有&#xff1a; fi,jmin⁡k1i−1fk,j−1Ck1,if_{i,j}\min_{k1}^{i-1}f_{k,j-1}C_{k1,i} f…

.NET Core 的Generic Host 之Generic Host Builder

通用Host(Generic Host) 与 web Host 不同的地方就是通用Host解耦了Http请求管道&#xff0c;使得通用Host拥有更广的应用场景。比如&#xff1a;消息收发、后台任务以及其他非http的工作负载。这些场景都可以通过使用通用Host拥有横切&#xff08;Cross-cutting&#xff09;的…

loj#2143. 「SHOI2017」组合数问题

loj#2143. 「SHOI2017」组合数问题 题目描述 Solution 考虑转化一下我们要求的东西。 ∑i0n(nkikr)∑i0n(nki)[i≡r(modk)]\sum_{i0}^{n}\binom{nk}{ikr}\sum_{i0}^{n}\binom{nk}{i}[i \equiv r \;\;(mod\;\;k)]∑i0n​(ikrnk​)∑i0n​(ink​)[i≡r(modk)] 这个式子是什么…

.NET Core微服务 权限系统+工作流(二)工作流系统

一、前言接上一篇 .NET Core微服务 权限系统工作流&#xff08;一&#xff09;权限系统 &#xff0c;再来一发工作流&#xff0c;我在接触这块开发的时候一直好奇它的实现方式&#xff0c;翻看各种工作流引擎代码&#xff0c;探究其实现方式&#xff0c;个人总结出来一个核心要…

LuoguP5504 [JSOI2011]柠檬

LuoguP5504 [JSOI2011]柠檬 题目描述 Solution 容易发现一个性质&#xff1a;每一段划分区间的首尾两个元素相同。 因为倘若不相同的话其中至少一个元素也就不产生贡献&#xff0c;将其划分在其他区间一定不会变劣。 因此就可以写出一个简单的O(n2)O(n^2)O(n2)的dpdpdp。 f…

开源分布式Job系统,调度与业务分离-如何创建一个计划HttpJob任务

项目介绍&#xff1a;Hangfire&#xff1a;是一个开源的job调度系统,支持分布式JOB&#xff01;&#xff01;Hangfire.HttpJob 是我针对Hangfire开发的一个组件,该组件和Hangfire本身是独立的。可以独立更新Hangfire版本不影响&#xff01;该组件已被Hangfire官方采纳&#xff…

LuoguP5366 [SNOI2017]遗失的答案

LuoguP5366 [SNOI2017]遗失的答案 题目描述 Solution 可以先简化问题&#xff0c;特判LLL不是GGG倍数的情况。 然后令n⌊nG⌋n\lfloor \frac{n}{G} \rfloorn⌊Gn​⌋,L⌊LG⌋L\lfloor \frac{L}{G} \rfloorL⌊GL​⌋。 现在相当于求出1...n1...n1...n中选择若干数&#xff0c…