我正在寻找一种用于线程间通信的解决方案。 线程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);
答案 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中使用新的async
和await
关键字,您可以大大简化代码。
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
。第一个调用在任务开始之前执行,第二个调用将在任务完成后执行。