2013-01-02 34 views
1

我是C#的新手,无法搞清楚如何将事件从线程传递到GUI窗体线程。任何帮助,将不胜感激。我发现的所有例子都太复杂了。我只想从处理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; } 
} 

}

回答

1

您是否必须使用此自定义线程系统,或者您是否能够使用BackgroundWorkersBackgroundWorkers避免了一个事件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方法。

+0

谢谢你的快速反应。以后我会考虑BackgrounWorkers。目前,我想将一个来自通用线程的事件传递回GUI窗体。尽管你的代码块stil并没有向我解释。我对csharp非常陌生。我假设你的代码会在GUI代码中上升,但是如何在线程中触发事件? – Bob

+0

我已更新帖子,希望有所帮助。你缺少的关键是附加的事件处理程序。主要要注意的是,即使UI线程设置了事件处理程序,工作实际上是在后台线程上完成的。 – keyboardP

+0

@keyboardP先生你可以请看看我的问题:[http:// stackoverflow。COM /问题/ 14198145/Windows的手机-7-如何对通知-数据被更新的功能于列表框(http://stackoverflow.com/questions/14198145/windows-phone-7-how-to -notify-数据被更新的功能于列表框) –

1

您需要将Form1注册为事件的侦听器。首先,添加一个方法类似下面到Form 1:

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(); 
} 
相关问题