将 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
.
将 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
.