【问题标题】:c# calling back to main threadc#回调主线程
【发布时间】:2010-10-14 09:58:25
【问题描述】:

我在后台线程的静态类中,但我想创建一个新的 GUI 组件,为此我需要应用程序的主线程来执行该方法。

我该怎么做?

[注意我不认为我可以使用 InvokeRequired 作为它的静态类而不是 gui]

大卫

【问题讨论】:

标签: c# .net winforms


【解决方案1】:

为了澄清这个问题,您在辅助线程上有一个静态类,您希望主线程从该类生成一个 UI 元素。

为此,您需要在静态类中设置一个事件,然后让您的 UI 监听该事件。即使它是静态的,也可以连接起来。 在您的事件句柄代码中,您可以调用主 UI 调用来实际生成 UI 元素。

class Program
{
    static void Main(string[] args)
    {
        DoSomething.OnNeedsUI += new EventHandler<EventArgs>(DoSomething_OnNeedsUI);
        Thread t = new Thread(new ThreadStart(DoSomething.Work));
        t.Start();
    }

    private static void DoSomething_OnNeedsUI(object sender, EventArgs e)
    {
        Console.Write("Call Back Handled Here");
    }
}


public static class DoSomething
{
    public static void Work()
    {
        for (int i = 0; i < 10; i++)
        {

            Thread.Sleep(5000);
            // Raise your Event so the tUI can respond
            RaiseOnNeedsUI();
        }
    }

    //  Create a Customer Event that your UI will Register with
    public static event EventHandler<EventArgs> OnNeedsUI;
    private static void RaiseOnNeedsUI()
    {
        if (OnNeedsUI != null)
            OnNeedsUI(null, EventArgs.Empty);
    }

【讨论】:

  • 澄清一下,这个示例仍然需要在事件处理程序中调用,对吗? (如解决方案中所述)事件本身不会跨线程,对吧?
  • 这个答案是错误的——DoSomething_OnNeedsUI 将在这里执行在工作线程中,而不是在主线程中。事件只是多播委托——它们不会神奇地跨越线程边界。
【解决方案2】:

您的静态类需要对在 UI 线程上创建的某个实例类的引用,最好是控件。由于您正在创建一个控件,因此您可能已经为该控件考虑了一些表单/窗口,因此无论如何您都需要一个参考。您可以使用表单的 Invoke() 方法来编组一个调用,该调用将在 UI 线程上创建控件。

【讨论】:

  • 静态类正在通过激活器创建一个组件并返回它,所以我没有对 gui 组件的引用...是重构的唯一选择,以便我这样做?
  • 除了枚举与进程关联的所有线程并进行疯狂猜测之外,我想不出一种方法来明确获取 UI 线程。我查看了 Application 类和 System.Threading.Thread 的属性,但似乎没有任何答案。
  • +1,因为我已经重构以将其用作解决方案 [在 Salizar 回答之前]。
【解决方案3】:

您可以将 UI 控件的实例传递给该方法(然后调用该方法),或者将您想要的内容封装为委托;例如:

static void DoStuff(..., Action<string> updateMessage) {
    ...
    //loop
    updateMessage(currentState);
}

与:

DoStuff(..., msg => this.Invoke((MethodInvoker)delegate{
    this.Text = msg;
}));

【讨论】:

  • 我不完全确定这会奏效;静态类不是无法访问 this 引用吗?我可能只是缺少一些上下文。
  • @OwenP - 如果你将它作为参数传递给方法,它是完全可访问的......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-20
  • 1970-01-01
  • 2014-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多