【问题标题】:Complex multi-threaded interface复杂的多线程接口
【发布时间】:2011-05-12 05:42:47
【问题描述】:

首先它不是我想要的闪屏...只是为了清楚...好的...让我们去描述问题:

我有一个表单可以触发 N 个线程(我不知道有多少,用户必须选择)...每个线程都有一个对象,并且在几分钟内,对象可能会触发一个事件以发出一些变化的信号。 . 每个线程都必须有一个表单来“报告”事件发送的消息...

我的问题是:线程完美地创建了表单……但是消失了……不知从何而来……它们出现在屏幕上……然后消失了……噗……消失了!我怎样才能避免这种不受欢迎的“处置”?!?!

【问题讨论】:

    标签: winforms multithreading c#-4.0


    【解决方案1】:

    如果您在线程中创建表单,则该表单将在线程完成后消失。如果您希望表单的存活时间超过您需要保持线程处于活动状态,或者在应用程序的主线程上创建表单。后者会更可取。只需确保每个都为相应表单中的对象挂钩事件侦听器,并在更新表单时根据需要使用InvokeBeginInvoke

    一个简单的例子:

    首先是一个工人: 类工人 { 公共事件EventHandlerSomethingHappened;

        protected void OnSomethingHappened(EventArgs e)
        {
            var evnt = SomethingHappened;
            if (evnt != null)
            {
                evnt(this, e);
            }
        }
        public void Work()
        {
            // do lots of work, occasionally calling
            // OnSomethingHappened
        }
    }
    

    然后,在一个表单中,我们有一个针对 SomethingHappened 事件的事件处理程序:

    public void SomethingHappenedHandler(object sender, EventArgs e)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new Action(() => SomethingHappenedHandler(sender, e)));
            return;
        }
    
        // update gui here
    }
    

    那么这真的只是将它们连接在一起的问题:

    Worker w = new Worker();
    ProgressForm f = new ProgressForm;
    w.SomethingHappened += f.SomethingHappenedHandler; 
    f.Show();   
    Thread t = new Thread(w.Work);
    t.Start();
    

    免责声明:这个样本很快就被扔在一起并且有些未经测试(坐在火车上,即将下车;))。

    【讨论】:

    • 我该怎么做?从一个线程调用主窗体并创建一个新窗体?
    • 我并没有这样做,但我使用了这个想法。谢了!
    【解决方案2】:

    Form 必须托管在具有消息循环的线程上。您可以通过调用Application.RunForm.ShowDialog 创建消息循环。但是,除非您有充分的理由这样做,否则我会避免有多个线程带有 Windows 消息循环。

    我也会避免创建 N 个线程。除了每个操作创建一个线程之外,还有更好的方法可以并行化 N 个操作。仅举两个例子:1) 在ThreadPool 中排队工作项或2) 通过Task 类使用任务并行库。创建 N 个线程的问题是每个线程都会消耗一定数量的资源。更多线程意味着将消耗更多资源并且将发生更多上下文切换。在多线程世界中,更多并不总是更好。

    【讨论】:

    • 我正在使用 .Net 3.5,没有任务的......呜咽......并且它要求用户必须定义​​同时工作的线程数......
    • @Leonardo:Microsoft 有一个 Task Parallel Library 的反向移植,其中包括 Task 类,可通过 Reactive Extensions 下载用于 .NET 3.5。只需谷歌即可。
    • @Leonardo:让用户指定线程数更糟糕。对于最佳线程数应该是多少,最终用户无法始终如一地做出比开发人员更好的判断。
    • 是的...我知道...我能做什么?!?!那家伙说他想要那样,不会采取任何其他方式......而且......我需要吃2个......
    【解决方案3】:

    你的线程必须是

    • 使用适当的 InvokeRequired + Invoke 逻辑
    • 或运行自己的 MessagePump (Application.Run)

    你(没)做过哪一个?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-25
      • 2013-08-22
      • 2011-01-02
      • 2012-10-25
      • 1970-01-01
      • 2019-04-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多