日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時(shí)間:2023/12/4 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 出让执行权:Task.Yield, Dispatcher.Yield 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一個(gè)耗時(shí)的任務(wù),可以通過(guò) Task.Yield 或者 Dispatcher.Yield 來(lái)中斷以便分割成多個(gè)小的任務(wù)片段執(zhí)行。

Yield?這個(gè)詞很有意思,叫做“屈服”“放棄”“讓步”,字面意義上是讓出當(dāng)前任務(wù)的執(zhí)行權(quán),轉(zhuǎn)而讓其他任務(wù)可以插入執(zhí)行。Task、Dispatcher、Thread?都有?Yield()?方法,看起來(lái)都可以讓出當(dāng)前任務(wù)的執(zhí)行權(quán)。



本文內(nèi)容
  • Dispatcher.Yield

    • 需要注意

  • Task.Yield


如果在閱讀中發(fā)現(xiàn)對(duì)本文涉及到的一些概念不太明白,可以閱讀:

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

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


如果一個(gè)方法的實(shí)現(xiàn)比較耗時(shí),為了不影響 UI 的響應(yīng),你會(huì)選擇用什么方法呢?我之前介紹過(guò)的?Invoke 和 InvokeAsync?可以解決,將后續(xù)耗時(shí)的任務(wù)分割成一個(gè)個(gè)小的片段以低于用戶輸入和渲染的優(yōu)先級(jí)執(zhí)行。

Dispatcher.Yield?也可以,其行為更加類似于?Dispatcher.InvokeAsync(即采用?Dispatcher?調(diào)度的方式,事實(shí)上后面會(huì)說(shuō)到其實(shí)就是調(diào)用了?InvokeAsync),而非?Dispatcher.Invoke(即采用?PushFrame?新開消息循環(huán)的方式)。

使用時(shí)需要?await:

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

這樣,這個(gè)?foreach?將在每遍歷到一個(gè)集合項(xiàng)的時(shí)候中斷一次,讓 UI 能夠響應(yīng)用戶的交互輸入和渲染。

Yield?方法可以傳入一個(gè)優(yōu)先級(jí)參數(shù),指示繼續(xù)執(zhí)行后續(xù)任務(wù)的優(yōu)先級(jí)。默認(rèn)是?DispatcherPriority.Background,低于用戶輸入?DispatcherPriority.Input、 UI 邏輯?DispatcherPriority.Loaded?和渲染?DispatcherPriority.Render。

Dispatcher.Yield?是如何做到出讓執(zhí)行權(quán)的呢?

查看源碼,發(fā)現(xiàn)?DispatcherYield?的返回值是?DispatcherPriorityAwaiter,而它的?OnCompleted?方法是這樣的:

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

所以,其實(shí)真的就是?InvokeAsync。如果希望了解為何是?OnCompleted?方法,可以閱讀?【C#】【多線程】【05-使用C#6.0】08-自定義awaitable類型 - L.M。

Dispatcher.Yield?是?Dispatcher?類型的靜態(tài)方法,而不是像?InvokeAsync一樣是實(shí)例方法。不過(guò) C# 有一個(gè)神奇的特性——靜態(tài)方法和實(shí)例方法可以在同一上下文中調(diào)用,而不用擔(dān)心產(chǎn)生歧義。

例如:

using System.Windows.Threading;

class Demo : DispatcherObject
{
void Test()
{
// 調(diào)用靜態(tài)方法 Yield。
await Dispatcher.Yield();
// 調(diào)用實(shí)例方法 InvokeAsync。
await Dispatcher.InvokeAsync(() => { });
}
}

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


拿前面?Dispatcher.Yield?的例子,我們換成?Task.Yield:

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

效果與?Dispatcher.Yield(DispatcherPriority.Normal)?是一樣的。因?yàn)?Task?調(diào)度回到線程上下文靠的是?SynchronizationContext,WPF UI 線程的?SynchronizationContext?被設(shè)置為了?DispatcherSynchronizationContext,使用?Dispatcher?調(diào)度;而?DispatcherSynchronizationContext?構(gòu)造時(shí)傳入的優(yōu)先級(jí)默認(rèn)是?Normal,WPF 并沒有特殊傳入一個(gè)別的值,所以 WPF UI 線程上使用?Task.Yield()?出讓執(zhí)行權(quán)后,恢復(fù)時(shí)使用的是?Normal?優(yōu)先級(jí),相當(dāng)于 Dispatcher.Yield(DispatcherPriority.Normal)。

希望了解?Dispatcher?和?SynchronizationContext?的區(qū)別可以閱讀?c# - Difference between Synchronization Context and Dispatcher - Stack Overflow。

DispatcherSynchronizationContext?執(zhí)行?await?后續(xù)任務(wù)的上下文代碼:

/// <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?優(yōu)先級(jí),那么在 UI 線程上的效果自然不如?Dispatcher.Yield。但是,Task.Yield?適用于任何線程,因?yàn)?SynchronizationContext?本身是與?Dispatcher?無(wú)關(guān)的,適用于任何線程。這樣,于如果一個(gè)?Task?內(nèi)部的任務(wù)太耗時(shí),用?Task.Yield?則可以做到將此任務(wù)分成很多個(gè)片段執(zhí)行。

如果覺得?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社區(qū)新聞,深度好文,歡迎訪問公眾號(hào)文章匯總?http://www.csharpkit.com?

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的出让执行权:Task.Yield, Dispatcher.Yield的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 风间由美一区二区 | 女人扒开屁股让男人桶 | 日本中文字幕精品 | av有声小说一区二区三区 | 爱吃波客今天最新视频 | 日本免费www | 高h捆绑拘束调教小说 | av网站有哪些 | 中文字幕亚洲无线码在线一区 | 毛片网| 久久久久久久久久久91 | 午夜宅男在线 | 日本亚洲欧洲色 | 女女互慰揉小黄文 | 天堂中文8 | 亚洲爆爽| 最近日本中文字幕 | 天天色av | 天天干天天操天天舔 | 色吊妞 | 窝窝午夜视频 | 激情 亚洲 | 国产91成人| 国产精品v日韩精品v在线观看 | 中文字幕在线乱 | 午夜精品久久久久久久 | 九九在线精品视频 | 每日在线更新av | 一级片视频在线观看 | 久久精品丝袜 | 色哟哟av| 国产精品suv一区二区 | 中文有码在线观看 | 91亚瑟视频| 国产av人人夜夜澡人人爽麻豆 | av手机在线免费观看 | 一级黄色a毛片 | 精品乱子一区二区三区 | 国产福利短视频 | 欧美呦呦呦 | 青草av在线| 亚洲欧美第一页 | 天天插天天射天天干 | 欧美爱爱一区二区 | av在线在线 | 亚洲AV午夜福利精品一级无码 | www.精品国产 | 真人一毛片| 天天摸天天做天天爽水多 | 三级伦理视频 | 日韩色综合网 | 日日干视频 | 国产综合在线播放 | 国产成人精品毛片 | 欧美91在线 | 精品久久久久一区二区国产 | 国产污视频在线看 | av在线播放一区 | 性欧美视频在线观看 | 日韩毛片av| 天天舔天天爽 | 99热只有这里有精品 | 日韩精品tv | 天天摸夜夜添 | 99国产精品一区二区 | 国产对白videos麻豆高潮 | 中文在线字幕免费观 | 中文字幕一区二区三区乱码在线 | 欧美s码亚洲码精品m码 | 黄网在线播放 | 欧洲xxxxx| 四虎库| 一级全黄裸体免费视频 | 久久久久久久极品内射 | 欧美做受69 | 国产一区二区免费视频 | porn麻豆 | 91久久精品一区二区 | www黄色| 亚洲国产精品99久久久久久久久 | 国产原创剧情av | porn麻豆| 激情综合区 | 日韩影院在线 | 成人亚洲玉足脚交系列 | 国产亚洲毛片 | av不卡在线免费观看 | 久久国产精品国产精品 | 免费观看在线观看 | 成年人网站免费看 | 国产麻豆一区二区三区在线观看 | av不卡一区二区三区 | 香蕉视频免费在线播放 | 天天撸天天射 | 欧美又粗又长又爽做受 | 亚洲小说春色综合另类 | 国产理伦 | 精品资源成人 | 伊人激情 |