我在主线程中从辅助线程调用事件时遇到问题。事件处理程序不在主线程上执行。任何人都可以给我一些关于我做错的指示。
由于
namespace ThreadSyncExample
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("MainThread: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
Execute execThe = new Execute();
execThe.FinishedThread += (src, arg) =>
{
//This shoould be executed on MainThread right?
Console.WriteLine("Thread Id: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
};
execThe.Run();
Console.ReadKey();
}
}
class Execute
{
public void Run()
{
Thread exec = new Thread(() =>
{
Console.WriteLine("Worker Thread : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
OnFinishedThread();
});
exec.Start();
}
public event EventHandler FinishedThread;
protected virtual void OnFinishedThread()
{
if (null != FinishedThread)
{
EventArgs args = new EventArgs();
FinishedThread(this, EventArgs.Empty);
}
}
}
}
答案 0 :(得分:1)
C#事件基本上只是一个易于使用的代理集合,“触发”事件只会导致运行时循环遍历所有代理并一次触发它们。
因此,在Work线程上调用了OnFinishedThread事件处理程序。
如果您希望活动在主要主题上,则必须Invoke()
。
编辑:
您似乎无权访问表单或WPF(因此您无法访问Invoke()
)
因此,您必须通过线程同步过程手动编组对主线程的调用。这通常是一种痛苦。
最简单的解决方案可能就是简单地使用BackgroundWorker,因为这样您就不再需要手动封送对主线程的调用。
var worker = new BackgroundWorker();
worker.DoWork += (sender, e) =>
{
// call the XYZ function
e.Result = XYZ();
};
worker.RunWorkerCompleted += (sender, e) =>
{
// use the result of the XYZ function:
var result = e.Result;
// Here you can safely manipulate the GUI controls
};
worker.RunWorkerAsync();
答案 1 :(得分:1)
FinishedThread()事件处理程序将在执行Execute.Run()的同一线程上执行。仅仅因为你在main()中定义了FinishedThread事件处理程序的主体并不意味着main()以某种方式定义了它的执行上下文。
您可以使用一些机制来执行线程编组:
不要重复已经说明的内容,请查看此答案以获取有关编组的更多信息: