SynchronizationContext
介紹
SynchronizationContext允許一個線程和另外一個線程進行通訊,SynchronizationContext在通訊中充當傳輸者的角色。另外這里有個地方需要清楚的,不是每個線程都附加SynchronizationContext這個對象,只有UI線程是一直擁有的。
SynchronizationContext.Current 能得到當前被主UI線程接管過的對象SynchronizationContext。
這個對象有一個方法:SynchronizationContext.Send(SendOrPostCallback d,object state)
- d 為一個沒有返回值,并且具有一個Object類型傳入參數的委托(SendOrPostCallback )
- state 為執(zhí)行這個委托時的參數(object)
你現在需要在子線程運行的時候利用SynchronizationContext.Current 得到SynchronizationContext對象,然后在需要切回UI線程的地方使用:SynchronizationContext.Send(SendOrPostCallback d,object state);就可實現將委托的方法切回到UI線程上去執(zhí)行。
注意:SynchronizationContext的對象不是所有線程都被附加的,只有UI主線程會被附加。
對于UI線程來說,是如何將SynchronizationContext這個對象附加到線程上的呢?
在Form1 form = new Form1()之前,SynchronizationContext對象是為空,
而當實例化Form1窗體后,SynchronizationContext對象就被附加到這個線程上了。
所以可以得出答案了:
當Control對象被創(chuàng)建的同時,SynchronizationContext對象也會被創(chuàng)建并附加到線程上。
所以在使用時,一定要等窗體InitializeComponent(); 這個完成后 它才能得到一個不為NULL的對象。
Send()和Post()區(qū)別
- Send() 是簡單的在當前線程上去調用委托來實現(同步調用)。也就是在子線程上直接調用UI線程執(zhí)行,等UI線程執(zhí)行完成后子線程才繼續(xù)執(zhí)行。【常見的應用場景是:后臺線程執(zhí)行任務時,需要UI彈MessageBox,并等待用戶做選擇時,用Send方法即可】
- Post() 是在線程池上去調用委托來實現(異步調用)。這是子線程會從線程池中找一個線程去調UI線程,子線程不等待UI線程的完成而直接執(zhí)行自己下面的代碼。
Send方法詳細解釋
`SynchronizationContext.Send()` 方法是在同步上下文(SynchronizationContext)上執(zhí)行操作的方法。在C#中,可以通過這個方法將一個操作推到同步上下文的消息隊列中,使其在該上下文的線程中同步執(zhí)行。
`SynchronizationContext.Send()` 方法接受兩個參數:一個表示要執(zhí)行的操作的委托,另一個表示操作所需的狀態(tài)對象。該方法將狀態(tài)對象封裝在回調委托中并將其加入同步上下文的消息隊列中,等待該上下文有空閑時執(zhí)行。
class MyClass { private readonly SynchronizationContext context; public MyClass(SynchronizationContext context) { this.context = context; } public void SomeMethod() { context.Send(state => { // state 表示之前的狀態(tài)對象 // 在這里執(zhí)行需要同步執(zhí)行的操作 }, null); } }
在上面的代碼中,我們創(chuàng)建了一個名為 `MyClass` 的類,并使用 `context`(SynchronizationContext)在方法 `SomeMethod()` 中同步執(zhí)行操作。我們使用 `context.Send()` 方法將操作添加到同步上下文的消息隊列中,并等待執(zhí)行。
需要注意的是,`context.Send()` 方法會阻塞當前線程,直到該操作完成為止。如果你希望在后臺線程中執(zhí)行該操作,可以使用 `context.Post()` 方法,該方法會將操作放在消息隊列中等待執(zhí)行,但不會阻塞當前線程。
總之,SynchronizationContext.Send() 方法允許將操作同步地添加到同步上下文的消息隊列中,并等待該上下文有空閑時執(zhí)行。使用 Send() 方法時,需要注意在同步上下文的線程中執(zhí)行操作,以避免阻塞 UI 線程等問題。
參考
利用SynchronizationContext.Current在線程間同步上下文
線程中更新ui- SynchronizationContext-Post/Send方法-簡單實驗

浙公網安備 33010602011771號