如何将单个事件从线程向上传递到GUI表单线程

本文关键字:GUI 单线程 表单 单个 事件 线程 | 更新日期: 2023-09-27 17:50:21

我是c#的新手,我很难弄清楚如何将事件从线程传递到GUI表单线程。任何帮助都会很感激。我找到的所有例子都太复杂了。我只想从从treat到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; }
}

}

如何将单个事件从线程向上传递到GUI表单线程

您需要将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();
}

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

或者,如果你从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方法。

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