2015-02-24 69 views
2

它是安全的UI線程的TaskScheduler存儲在一個領域如下:將UI線程的TaskScheduler存儲在字段中是否安全?

class TaskSchedulerReference { 

    private readonly _uiTaskScheduler; 

    // Constructor is called by the UI Thead 
    public TaskSchedulerReference() { 
     _uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext() 
    } 

    public TaskScheduler UiTaskScheduler { get { return _uiTaskScheduler; } } 
} 

...所以有可能在任何時間從任何後臺線程通知UI在Task.ContinueWith(action, TaskSchedulerReference.UiTaskScheduler)回調。

是否保證在整個應用程序生命週期中引用仍然有效?

+2

這個靜態初始化器非常危險。請參閱[我的答案](http://stackoverflow.com/questions/25751465/prism-5-delegatecommandbase-raisecanexecutechanged-throws-invalidoperationexcept/27406194#27406194)我在哪裏解釋如何可以這樣的事情搞砸了整個應用程序。不保證該字段將在UI線程上初始化。 – dymanoid 2015-02-24 16:23:13

+0

請注意,這不是SC,它是使用SC的'TaskScheduler'。 – i3arnon 2015-02-24 16:59:22

+0

忘記靜態初始值設定項。這不是重點。我糾正了這個問題...... – jeromerg 2015-02-24 17:07:18

回答

5

除了那個可疑的// This class is first visited by the UI Thread,是的。相反,使用一個顯式的初始化器(顯式地從UI線程運行),JIT不保證在UI線程上運行類初始化器。

但是,我更喜歡將上下文捕獲爲局部變量。在多線程(和異步編程)中將任何東西公開爲全局狀態都很棘手。總是嘗試儘可能使用本地狀態。它也反映了舊的IsInvokeRequired模式。每種方法都應該非常明確地說明發生了什麼 - 這很容易導致無意中引入重入代碼和死鎖。

+0

謝謝。我的恐懼並不涉及靜態領域(這個例子只是爲了提供一個插圖):問題是:可能對SynchronizationContext的引用變得無效?特別是,我害怕調用'SynchronizationContext.SetSynchronizationContext(context)',這將使存儲的字段完全過時... – jeromerg 2015-02-24 17:05:18

+1

@jeromerg是啊,你不必擔心,在Windows窗體應用程序 - 如果您擁有多個同步上下文,那麼無論如何您都會遇到麻煩:D。但是,如果您發現自己編寫Web應用程序,那麼它將無法工作 - 這是傳遞上下文而不是將其放在全局字段中的另一個原因。 – Luaan 2015-02-25 08:28:42

0

如果你看看你code for FromCurrentSynchronizationContext可以看到,它通過捕獲SynchronizationContext.Current創建SynchronizationContextTaskScheduler

只要你在UI線程上做到這一點,就可以捕獲UI的SC,並且SynchronizationContext.SetSynchronizationContext(context)不能更改捕獲的上下文。

請注意,你存儲的是一個TaskScheduler持有SC而不是SC本身。如果你想捕捉SC只使用SynchronizationContext.Current

相關問題