将 UI 线程的 TaskScheduler 存储在字段中是否安全?

Is it safe to store in a field the TaskScheduler of the UI Thread?

将 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; } }
}

...以便可以随时从 Task.ContinueWith(action, TaskSchedulerReference.UiTaskScheduler) 回调中的任何后台线程通知 UI。

是否保证引用在整个应用程序生命周期内保持有效?

除了那个可疑的 // This class is first visited by the UI Thread,是的。相反,使用显式初始化程序(显式 UI 线程中的 运行),不保证 JIT 运行 UI 线程上的 class 初始化程序。

但是,我更喜欢将上下文捕获为局部变量。在多线程(和异步编程)中将任何东西公开为全局状态是很棘手的。始终尝试尽可能使用本地状态。它还散发着旧 IsInvokeRequired 模式的味道。每个方法都应该非常明确地说明发生了什么 - 否则很容易意外引入可重入代码和死锁。

如果您查看 code for FromCurrentSynchronizationContext,您会发现它通过捕获 SynchronizationContext.Current.

创建了一个 SynchronizationContextTaskScheduler

只要您在 UI 线程上执行此操作,您就会捕获 UI 的 SC,并且 SynchronizationContext.SetSynchronizationContext(context) 无法更改捕获的上下文。

请注意,您存储的是 TaskScheduler,其中包含 SC 而不是 SC 本身。如果你想捕获 SC 只需使用 SynchronizationContext.Current.