从库中捕获主线程 SynchronizationContext 或 Dispatcher

2024-05-18

我有一个 C# 库,希望能够将工作发送/发布到“主”ui 线程(如果存在)。 该库可供以下人员使用:

  • 一个winforms应用程序
  • 本机应用程序(带 UI)
  • 控制台应用程序(没有 UI)

在库中,我想在初始化期间捕获一些东西(SynchronizationContext、调度程序、任务调度程序或其他东西),这将允许我(稍后)将工作发送/发布到主线程(如果主线程具有这种能力——即它有一个消息泵)。例如,当且仅当主应用程序能够让我访问主线程时,库才会在主线程上放置一些 Winforms UI。

我尝试过的事情:

  1. A 同步上下文 http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx: 对于 Winforms 应用程序(aWindowsFormsSynchronizationContext http://msdn.microsoft.com/en-us/library/system.windows.forms.windowsformssynchronizationcontext.aspx将安装为Current http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.current.aspx同步上下文。这对于控制台应用程序也适用 - 因为我可以检测到 Current SynchronizationContext 为空(因此,知道我无法将工作发送/发布到主线程)。这里的问题是本机 UI 应用程序:它有能力(即它有消息泵),但当前同步上下文为空,因此我无法将其与控制台应用程序情况区分开来。如果我可以区分,那么我可以简单地在主线程上安装一个 WindowsFormsSynchronizationContext,然后我就可以开始了。
  2. A 调度员 http://msdn.microsoft.com/en-us/library/ms615907:使用捕获此Current http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.current.aspx创建一个新的 SynchronizationContext。因此,在所有情况下我都会找回调度程序。但是,对于控制台应用程序,使用Dispatcher.Invoke后台线程将挂起(如预期)。我可以用Dispatcher.FromThread http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.fromthread(如果线程不存在,则不会为线程创建调度程序)。但是本机 UI 应用程序将使用此方法返回 null 调度程序,因此我再次陷入无法区分 UI 应用程序和控制台应用程序的困境。
  3. A 任务调度器 http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.aspx: 我可以用来自当前同步上下文 http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.fromcurrentsynchronizationcontext.aspx。这与 SynchronizationContext 具有相同的问题。 IE。在调用 FromCurrentSyncronizationContext 之前,我必须检查 Current SynchronizationContext 是否为 null(控制台应用程序和本机 ui 应用程序就是这种情况)。因此,我再次无法区分本机 ui 应用程序和控制台应用程序。

当然,我可以让我的库的用户在调用我的库时指定它是否是 UI 应用程序Initialize方法,但我希望尽可能避免图书馆用户的这种复杂情况。


这通常是不可能的,易于在线程中使用的库无法对哪个特定线程是 UI 线程做出任何假设。您可以捕获 Synchronization.Current,但只有在从 UI 线程调用初始化方法时才能正常工作。这并不是什么特别不寻常的事情,就像 TaskScheduler.FromCurrentSynchronizationContext() 往往会偶然工作,但不能保证。您可以添加一个检查,如果 Thread.CurrentThread.GetApartmentState() 不返回 STA,那么您没有从 UI 线程调用的可能性非常高。在这种情况下,SynchronizationContext.Current 通常也将为 null,这是另一种检查方法。

(可以说)更好的方法是不用担心它并让客户端代码弄清楚它,它不会在整理回调时遇到任何问题。或者公开 SynchronizationContext 类型的属性,以便客户端代码可以分配它。或者将其添加为构造函数参数。如果您准备好 Post 但发现它仍然为 null,则抛出 InvalidOperationException,这是客户端程序员只犯一次的疏忽。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从库中捕获主线程 SynchronizationContext 或 Dispatcher 的相关文章

  • asp.net core / kestrel中的线程管理

    我正在解决我们已迁移到 asp net core 2 0 的 asp net 应用程序的性能 可扩展性问题 我们的应用程序作为应用程序服务托管在 azure 上 并且在任何中等流量的情况下都很容易崩溃 让我困惑的一件事是如何处理多个并发请求
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • Java执行器服务线程池[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果我使用 Executor 框架在
  • Java列表的线程安全

    我有一个列表 它将在线程安全上下文或非线程安全上下文中使用 究竟会是哪一个 无法提前确定 在这种特殊情况下 每当列表进入非线程安全上下文时 我都会使用它来包装它 Collections synchronizedList 但如果不进入非线程安
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐