启动多个gui(WinForms)线程,以便它们可以与C#中的一个主gui分开工作?

时间:2010-03-01 22:15:47

标签: c# .net winforms multithreading c#-3.0

我有一个MainForm窗口,用户可以按3个按钮。每个按钮都会启动新表单,用户可以在其中执行任何他喜欢的操作(例如耗时的数据库调用等)。所以我决定将每个表单放在它自己的线程中:

   private Thread subThreadForRaportyKlienta;
   private Thread subThreadForGeneratorPrzelewow;
   private Thread subThreadForRaporty;
   private void pokazOplatyGlobalne() {
           ZarzadzajOplatamiGlobalneDzp varGui = new ZarzadzajOplatamiGlobalneDzp();
           varGui.ShowDialog();
    }
    private void pokazRaportyKlienta() {
          RaportyDzpKlient varGui = new RaportyDzpKlient();
           varGui.ShowDialog();
    }       
    private void pokazRaportyWewnetrzne() {
       RaportyDzp varGui = new RaportyDzp();
        varGui.ShowDialog();
    }
    private void pokazGeneratorPrzelewow() {
        ZarzadzajPrzelewamiDzp varGui = new ZarzadzajPrzelewamiDzp();
        varGui.ShowDialog();
    }
    private void toolStripMenuGeneratorPrzelewow_Click(object sender, EventArgs e) {
        if (subThreadForGeneratorPrzelewow == null || subThreadForGeneratorPrzelewow.IsAlive == false) {
            subThreadForGeneratorPrzelewow = new Thread(pokazGeneratorPrzelewow);
            subThreadForGeneratorPrzelewow.Start();
        } else {

        }

    }
    private void toolStripMenuGeneratorRaportow_Click(object sender, EventArgs e) {
        if (subThreadForRaporty == null || subThreadForRaporty.IsAlive == false) {
            subThreadForRaporty = new Thread(pokazRaportyWewnetrzne);
            subThreadForRaporty.Start();
        } else {

        }
    }
    private void toolStripMenuGeneratorRaportowDlaKlienta_Click(object sender, EventArgs e)
    {
        if (subThreadForRaportyKlienta == null || subThreadForRaportyKlienta.IsAlive == false) {
            subThreadForRaportyKlienta = new Thread(pokazRaportyKlienta);
            subThreadForRaportyKlienta.Start();
        } else {

        }
    }

我有几个问题,希望有人能解释一下:

  1. 当我使用Show()代替ShowDialog()时,窗口只会眨眼一秒钟而且从不显示。这两者之间的实际差异是什么?为什么会发生?
  2. 当我使用ShowDialog时,一切看起来都很正常,但我注意到并非所有内容都在其中一个gui中正确填充(即使在Form_Load()中有3个简单的添加项,一个listView也会保持空白。我注意到了这一点只有在一个GUI中,即使您第一眼看到一切在其他两个gui中工作正常,我也可以在这些表单中执行多个任务,在背景中更新这些表单(从表单方法内部)。为什么这个不同?
  3. 这样做的正确方法是什么?在每个表单中执行的任务可能非常耗时,并且我希望用户可以在这4个窗口之间跳转而没有问题,这样他就可以执行他喜欢的操作。

4 个答案:

答案 0 :(得分:3)

区别在于Modal and Modeless Windows Forms

  

无模式表格让你转移   形式和另一个之间的焦点   形式,而不必关闭   初始表格

Show()方法用于此目的

答案 1 :(得分:3)

Show()显示新表单,然后返回。如果这是所有线程正在做的比线程将退出,那将破坏表单。

ShowDialog()显示表单,然后开始运行消息泵,直到表单被隐藏或销毁,ShowDialog()不返回,因此您的线程继续运行。

如果您的意思是这些表单的行为类似于单独的应用程序窗口。然后你也可以在form.Show()之后使用Application.Run()为该线程上的表单运行消息泵。这样做的缺点是,当你的任何一个表单被关闭时,由于WM_QUIT的处理方式,它最终可能会取消整个过程。

但除了处理关闭应用程序的方式之外,Form.ShowDialog()非常类似于Form.Show(),后跟Application.Run()。导致消息泵退出的条件在这些条件之间略有不同,因此您可以根据应用程序处理关闭其中一个表单的方式选择一个或另一个。

答案 2 :(得分:1)

您应该将耗时的任务放在他们自己的BackgroundWorker线程中。将所有表单保留在主线程中。

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

答案 3 :(得分:0)

1:Show()没有阻塞,即显示窗口然后返回。之后,varGui变量超出范围并由垃圾收集器=>完成。消失。

2:您需要显示更新代码以获得明确的答案,但因为您只能在创建表单的线程中运行时更新表单的内容。否则这样做是不可靠的,当表单更新不起作用时,通常的罪魁祸首也是如此。在表单类的方法中,调用:

if (InvokeRequired) { 
   .Invoke(..); // call back this same method on the right thread
} else {
 // dowork 
}

管理用户界面。

3:正确的方法是Jake所写的:对所有GUI内容使用一个线程,为后台工作使用BackgroundWorker线程。