线程之间通过代理进行通信?

时间:2013-10-25 10:30:01

标签: c# multithreading

我正在寻找一种用于线程间通信的解决方案。 线程A是Windows应用程序的主线程。我启动一个独立于线程a的线程B,它们不共享代码。但是线程A必须得到一些关于线程b状态的反馈。我试着用代表来解决这个问题。 我很抱歉,我忘了补充说我必须处理.net 3.5,c#,WEC7

代码

非常重要
public void OnMyEvent(string foo)
        {
            MessageBox.Show(foo);
        }

在线程a的上下文中执行,我该如何实现呢

public partial class Form1 : Form
{
//...
    public void StartThread(Object obj)
    {
        new ClassForSecondThread(obj as Parameters);            
    }

    private void button1_Click(object sender, EventArgs e)
    {
        //ParameterizedThreadStart threadstart = new ParameterizedThreadStart(startThread);
        ParameterizedThreadStart threadstart = new ParameterizedThreadStart(StartThread);
        Thread thread = new Thread(threadstart);
        Parameters parameters = new Parameters(){MyEventHandler = OnMyEvent};
        thread.Start(parameters);                        
    }

    public void OnMyEvent(string foo)
    {
        MessageBox.Show(foo);
    }
}

//This code is executed in Thread B
public class ClassForSecondThread
{
    public ClassForSecondThread(Parameters parameters)
    {
        if (parameters == null) 
            return;
        MyEventhandler += parameters.MyEventHandler;
        DoWork();
    }

    private void DoWork()
    {
        //DoSomething
        if (MyEventhandler != null)
            MyEventhandler.DynamicInvoke("Hello World");// I think this should be executed async, in Thread A
        Thread.Sleep(10000);
        if (MyEventhandler != null)
            MyEventhandler.DynamicInvoke("Hello World again"); // I think this should be executed async, in Thread A
    }

    public event MyEventHandler MyEventhandler;
}
public class Parameters
{
    public MyEventHandler MyEventHandler;
}

public delegate void MyEventHandler(string foo);

2 个答案:

答案 0 :(得分:2)

如果你想在主UI线程上调用MessageBox,你可以使用Control.Invoke实现你想要的。

     Invoke((MethodInvoker)(() => MessageBox.Show(foo)));

可以在表单上直接调用Invoke方法,并且您不会在委托中的线程B的上下文中 - 代码将在与表单相同的线程上运行。

编辑: OP问题:如果我正确理解Control.Invoke,它总是在控件的上下文中起作用吗?

虽然Invoke方法使用Control(在本例中为表单)来获取其运行的UI线程的句柄,但委托中的代码并不特定于UI。如果您想添加更多语句并将其展开以包含更多内容,请执行以下操作:

        string t = "hello"; //declared in the form

        //Thread B context - Invoke called
        Invoke((MethodInvoker)(() => 
            {
                //Back to the UI thread of the Form here == thread A 
                MessageBox.Show(foo);
                t = "dd";
            }));

此外,如果您要在多线程环境中更新数据可供多个线程访问的内容,那么您需要调查sychronization - 将锁应用于数据等。

答案 1 :(得分:1)

通过在C#5.0中使用新的asyncawait关键字,您可以大大简化代码。

public class Form1 : Form
{
  private async void button1_Click(object sender, EventArgs args)
  {
    OnMyEvent("Hello World");
    await Task.Run(
      () =>
      {
        // This stuff runs on a worker thread.
        Thread.Sleep(10000);
      });
    OnMyEvent("Hello World again");
  }

  private void OnMyEvent(string foo)
  {
    Message.Show(foo);
  }

}

在上面的代码中,在两种情况下都会在UI线程上执行OnMyEvent。第一个调用在任务开始之前执行,第二个调用将在任务完成后执行。