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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

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

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

?

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


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

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

Dispatcher.Yield

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

Dispatcher.Yield 也可以,其行為更加類似于 Dispatcher.InvokeAsync(即采用 Dispatcher 調(diào)度的方式,事實(shí)上后面會(huì)說到其實(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í)例方法。不過 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。

Task.Yield

拿前面 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í)行。


參考資料

  • https://stackoverflow.com/questions/23431595/task-yield-real-usages“>c# - Task.Yield - real usages? - Stack Overflow
  • Task.Yield Method (System.Threading.Tasks)
  • c# - Difference between Synchronization Context and Dispatcher - Stack Overflow

轉(zhuǎn)載于:https://www.cnblogs.com/walterlv/p/10236535.html

總結(jié)

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

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