1

我是 C# 新手,无法弄清楚如何将事件从线程传递到 GUI 表单线程。任何帮助,将不胜感激。我发现的所有例子都太复杂了。我只想从一个事件开始,从处理到 GUI,让 GUI 做一些事情(现在,任何事情)。

namespace testEvents
{
public delegate void StuffHappenedDel( MessageEventArgs e);

public partial class Form1 : Form
{


    workerThread thread;
    int j = 0;
    public Form1()
    {
        InitializeComponent();
        thread = new workerThread();
        thread.Start();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        thread.Stop();
    }



    private void StuffHappenedDel(Object seder, EventArgs e)
    {
        j++;
    }


}

public class workerThread
{
    Thread worker;
    private bool _quit = false;

    /*  I don't think this next line is correct*/
    public event StuffHappenedDel StuffHappened;


    protected virtual void OnStuffHappened(MessageEventArgs e)
    {
        if (StuffHappened != null)
            StuffHappened( e);
    }


    public void Start()
    {
        ThreadStart start = new ThreadStart(Run);
        worker = new Thread(start);
        worker.Start();
    }

    private void Run()
    {
        int i = 0;
        while (!_quit)
        {
            Thread.Sleep(1000);
            i++;
            OnStuffHappened(new MessageEventArgs(false, "it worked!"));
            Console.WriteLine(string.Format("Slept {0} seconds.",i));
        }
        Console.WriteLine("Thread exiting");
    }
}


public class MessageEventArgs : EventArgs
{
    public MessageEventArgs(bool Error, string message)
    {
        IsError = Error;
        Message = message;
    }

    public bool IsError { get; set; }
    public string Message { get; set; }
}

}

4

3 回答 3

1

你必须使用这个自定义线程系统,还是可以使用BackgroundWorkers?有一个在创建 BackgroundWorker 的线程上触发BackgroundWorkers的事件。ProgressChanged

或者,如果您从 UI 线程将处理程序附加到后台事件,则工作仍然在后台线程上完成。

thread.StuffHappenedDel += new EventHandler<MessageEventArgs>(StuffHappenedDel);

因此,您需要将数据编组到 UI 线程。一种方法是使用BeingInvoke.

private void StuffHappenedDel(object sender, MessageEventArgs e)
{
    this.myControl.BeginInvoke( new Action(
     () => 
     {
           //UI thread work (likely anything that affects UI. Heavy      
          //processing can continue on the bg thread outside this code block
     }));
}

此外,您可以if (myControl.InvokeRequired)在更改特定控件时检查是否需要编组数据。

  if (this.InvokeRequired)
  {
       this.Invoke((Action)(() =>
       {
           //UI thread stuff
       }
       ));
  }

编辑以澄清

您创建的线程对象需要将事件处理程序附加到StuffHappenedDel事件。为此,您可以使用类似这样的东西

thread.StuffHappenedDel += new EventHandler<MessageEventArgs>(StuffHappenedDel);

在你打电话之前thread.Start()。现在,这个处理程序被称为

private void StuffHappenedDel(Object seder, MessageEventArgs e)
{
    j++;
}

每当您的事件被触发时。

如果要对任何 UI 元素进行更改,则需要使用上述Invoke方法。

于 2013-01-02T17:38:59.663 回答
1

您需要将 Form1 注册为事件的侦听器。首先,在 Form1 中添加如下方法:

private void thread_SuffHappened(MessageEventArgs e)
{
    MessageBox.Show("Stuff happened!");
}

在 Form1 的构造函数中,像这样注册为侦听器:

public Form1()
{
    InitializeComponent();
    thread = new workerThread();
    thread.StuffHappened += new StuffHappenedDel(thread_StuffHappened);
    thread.Start();
}
于 2013-01-02T17:45:35.467 回答
0

查看后台工人类。此外,您始终可以触发由 GUI 类处理的事件(尽管不在 GUI 线程上),然后调用Invoke

于 2013-01-02T17:36:51.987 回答