代码之家  ›  专栏  ›  技术社区  ›  Arya

多线程多类gui应用程序,我做得对吗?

  •  2
  • Arya  · 技术社区  · 14 年前

    我创建了下面的项目,向你们展示我是如何计划做事的。但我的主要项目将更大,将有多个类。我只是想让它正常工作,所以我知道我在编码时使用了良好的实践。

    这是我的表格代码

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace Test
    {
      public partial class Form1 : Form
      {
        public Form1()
        {
          InitializeComponent();
        }
    
        delegate void Class1Deligate();
    
        private void button1_Click(object sender, EventArgs e)
        {
          Class1 c = new Class1();
          Class1Deligate testMethod = new Class1Deligate(c.testtest);
          testMethod.BeginInvoke(endTestMethod, testMethod);
        }
    
        void endTestMethod(IAsyncResult ar)
        {
    
        }
      }
    }
    

    这是我的一班代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;
    
    namespace Test
    {
      class Class1
      {
        public void testtest()
        {
          Thread.Sleep(8888);
          MessageBox.Show("Done");
        }
      }
    }
    

    致意

    4 回复  |  直到 13 年前
        1
  •  1
  •   Dinah SLaks    14 年前

    我不认为你真的开始 线。 delegate.BeginInvoke 可能使用内部线程池来完成它的竞标。另外,我觉得你不应该打电话 BeginInvoke 没有合适的 EndInvoke IAsyncResult 异步调用

    如果需要新线程,可以使用 Thread

    Thread t = new Thread(c.testtest);
    t.IsBackground = true; // end if main thread ends
    t.Start();
    

    注意,如果您使用如上所述的线程类,并且使用GUI,则需要向GUI线程附加一个方法来更新它。您可以使用Control.Invoke调用

    public void updateGUI(object state) {
        if (control.InvokeRequired) {
            control.Invoke(new Action<object>(updateGUI), state);
            return;
        }
        // if we are here, we can safely update the GUI
    }
    
        2
  •  0
  •   mike    14 年前

    首先,有 ThreadPool 如果您愿意,类可用于线程。这是我通常用来触发新线程的方法,例如。,

    ThreadPool.QueueUserWorkItem(f.ThreadPoolCallback, i);
    

    delegate void ChangeFormUnsafeCallback(string text);
    private void ChangeFormUnsafe(string text)
    {
      // Do stuff to form/controls
    }
    
    private void SomeFunction()
    {      
      myForm.Invoke(new ChangeFormUnsafeCallback(ChangeFormUnsafe), "foo");
    }
    

    您可以检查是否需要调用,但是通常很容易知道该函数是否将在UI线程中使用并进行适当的调用。作为一般经验法则,除非您的函数是由于窗体上发生的事情(例如,单击按钮)而运行的,否则您将需要使用Invoke函数。

        3
  •  0
  •   dashton    14 年前

    艾莉亚

        void button1_Click(object sender, EventArgs e)
        {
            Class1 c = new Class1();
            Action action = c.Test;
    
            action.BeginInvoke(new AsyncCallback(EndTestMethod), null);
        }
        void EndTestMethod(IAsyncResult token)
        {    
            Action callBack = (Action)((AsyncResult)token).AsyncDelegate;
            callBack.EndInvoke(token);
        }
    

    如果您的方法寿命很短并且需要回调,则异步委托方法非常有用。否则,对于长时间运行的进程,您可能需要创建并启动一个新线程。

     Thread t = new Thread(c.Test);
            t.IsBackground = true;
            t.Start();
    

    对于Dispatcher,这是一个WPF类,它将WPF应用程序中要由UI线程处理的操作排队(除其他外)。从代码来看,您似乎正在编写Winforms应用程序,因此这种类型不合适。

    最后,为了更新文本框,需要检查是否试图在创建控件的同一线程(UI线程)上访问该控件。这是通过control.invokerequired和control.invoke完成的。具体如下:

           void AddText(string text)
        {
            if (textBox1.InvokeRequired)
            {
                textBox1.Invoke((Action<string>)AddText, text);
            }
            textBox1.Text = text;
        }
    
        4
  •  0
  •   Community Mr_and_Mrs_D    7 年前

    different 你能走的路。如果有一个要在不阻塞UI线程的情况下执行的任务,可以使用 BackgroundWorker . 这将为您提供一种非常简单的方法来保持UI的快速性,并且它使更新UI变得容易,而不需要调用等。

    如果你要完成很多任务,你可能应该使用 ThreadPool . 如果您需要为线程分配优先级,或者它们将花费大量时间阻塞,那么您应该创建自己的实例线程。

    当然,您可以继续使用线程池的方式来做事情,但是还有其他方法可以更好地满足您的特定需求。