我有一个 C# 库,它希望能够将工作发送/发布到“主”ui 线程(如果存在)。该库可用于:
- 一个winforms应用程序
- 本机应用程序(带有 UI)
- 控制台应用程序(没有 UI)
在库中,我想在初始化期间捕获一些东西(A SynchronizationContext、Dispatcher、Task Scheduler 或其他东西),这将允许我(稍后)将工作发送/发布到主线程(如果主线程具有这种能力——即它有一个消息泵)。例如,当且仅当主应用程序有能力让我进入主线程时,库才会在主线程上放置一些 Winforms UI。
我尝试过的事情:
- SynchronizationContext :捕获这对于Winforms 应用程序很好(WindowsFormsSynchronizationContext将作为当前SynchronizationContext 安装。这也适用于控制台应用程序 - 因为我可以检测到 Current SynchronizationContext 为空(因此,知道我没有'没有能力向主线程发送/发布工作)。这里的问题是本机 UI 应用程序:它有能力(即它有一个消息泵),但当前同步上下文为空,因此我可以' t将它与控制台应用案例区分开来。如果我能区分,那么我可以简单地在主线程上安装一个 WindowsFormsSynchronizationContext,我很高兴。
- Dispatcher :使用Current捕获它会创建一个新的 SynchronizationContext。因此,在所有情况下,我都会取回一个 Dispatcher。但是,对于控制台应用程序,
Dispatcher.Invoke
从后台线程使用将挂起(如预期的那样)。我可以使用Dispatcher.FromThread
(如果线程不存在,它不会为线程创建 Dispatcher)。但是本机 UI 应用程序将使用此方法返回一个 null Dispatcher,因此我再次陷入无法区分 UI 应用程序和控制台应用程序的问题。 - 一个TaskScheduler:我可以使用FromCurrentSynchronizationContext。这与 SynchronizationContext 有相同的问题。即在调用 FromCurrentSynchronizationContext 之前,我必须检查 Current SynchronizationContext 是否为空(控制台应用程序和本机 ui 应用程序就是这种情况)。所以,我再次无法区分本机 ui 应用程序和控制台应用程序。
当然,我可以让我的库的用户在调用我的方法时指定它是否是 UI 应用程序Initialize
,但我希望尽可能避免库用户出现这种复杂情况。