1

我正在寻找线程间通信的解决方案。线程 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);
4

2 回答 2

2

当您想在主 UI 线程上调用 MessageBox 时,您可以使用Control.Invoke.

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

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

编辑: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";
            }));

此外,如果您在多线程环境中更新内容,其中数据可以被多个线程访问,那么您将需要研究同步- 对数据应用锁等。

于 2013-10-25T10:40:01.073 回答
1

值得一提的是,您可以通过使用 C# 5.0 中的 newasyncawait关键字大大简化您的代码。

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);
  }

}

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

于 2013-10-25T14:31:22.387 回答