【问题标题】:Forcing code execution on main thread强制在主线程上执行代码
【发布时间】:2009-04-24 21:32:12
【问题描述】:

如何强制在我的主线程上执行一段代码?

这就是我想知道的原因:

我有一个自定义创建的消息框,有时会从不是主线程的线程中显示。但是,当调用消息框构造函数时,我得到一个 InvalidOperationException 说“调用线程必须是 STA,因为许多 UI 组件都需要这个。”这是有道理的,UI 元素需要在主线程上处理。

我的 MessageBox.ShowMessage(...) 函数是一个静态函数,它创建我的自定义消息框的实例并显示它。我可以在 ShowMessage 中放入一些东西来强制创建消息框并在主线程上显示吗?在我的代码的其他地方,我使用 Control.BeginInvoke 来处理类似的问题,但由于它是一个静态函数,因此没有现有的 UI 元素可供我调用 BeginInvoke。

我必须从 Control.BeginInvoke 调用 MessageBox.ShowMessage 吗?我更喜欢从 ShowMessage 中调用 BeginInvoke(或类似的)。

【问题讨论】:

    标签: c# wpf multithreading


    【解决方案1】:

    这里有几个选项:

    • 制作第二个线程 STA(您只能为自己的 Thread 执行此操作 - 不适用于 ThreadPool 线程) - 通过 .SetApartmentState(ApartmentState.STA);
    • 查看SynchronizationContext.Current是否为非空;如果是这样,请使用Send/Post
    • 将表单/控件作为 ISynchronizeInvoke 实例传递(可能不适用于 WPF - 我不能 100% 确定)

    【讨论】:

    • 您是否有链接说明如何实施您列出的第一个选项?
    • 创建线程时,只需调用 .SetApartmentState ,如(已编辑)答案所示。如果您首先需要更多帮助来创建主题,请告诉我。
    • 这些选项是否比其他选项更好?拥有多个线程 STA 是一种好习惯吗? SynchronizationContext.Current 为 null,是否意味着取消了该选项?
    • Marc,你能解释一下这是否比告诉主窗体调用消息框更好/更糟吗?
    • @balabaster - 不同。我可能只喜欢一个 STA,但任何一个都适用于 AFAIK。
    【解决方案2】:

    你的想法是对的——为了让它正常工作,你需要从主线程中调用它。

    最简单的方法?启动主窗体时,将引用保存在对 ShowMessage() 调用可见的静态变量中。然后,你的 ShowMessage 就可以做标准了:

    if(myForm.InvokeRequired)
    {
         myForm.Invoke(() => ShowMessage(arg1,arg2,arg3));
         return;
    }
    .... other code here....
    

    【讨论】:

    • 他实际上可能不需要显式变量——在 WPF 中他可以使用 Application.Current.MainWindow,在 WinForms 中可以使用 Application.OpenForms 集合中的一个窗口。
    【解决方案3】:

    不直接显示消息框,只需向主线程发送消息,这会通知主线程显示消息框。

    【讨论】:

    • 你能举个例子说明如何做到这一点吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    • 1970-01-01
    • 2020-08-15
    相关资源
    最近更新 更多