在c#中通过线程调用其他类的事件
本文关键字:其他 事件 调用 线程 | 更新日期: 2023-09-27 17:49:44
情况如下:
我有一个类,创建一个主表单。它将主窗体的创建对象保持为静态成员,如下所示:
public static mainAppWnd;
和窗体是在main
代码的某个地方创建的,像这样:
mainAppWnd = new MainAppWnd();
现在,我必须每次只打开这个应用程序的一个实例,我通过互斥来做到这一点。这部分很好。当打开该应用程序的第二个实例时,我必须检查它是否包含一些命令行参数。如果是这样,我必须将这些命令行参数传递给现有的运行实例,并且在运行实例中,我必须打开一个新表单。这个新表单的打开将在MainAppWnd
类内部处理。为了做到这一点,我使用了管道,并在线程中使用了Listen
。我的线程函数是这样的:
public static void Listen()
{
NamedPipeServerStream server = new NamedPipeServerStream("49A252BB-C0FC-4bdb-8CA7-522A3BAE3432");
server.WaitForConnection();
byte[] buffer = new byte[1000];
int bytesread = server.Read(buffer, 0, 1000);
string args = Encoding.UTF8.GetString(buffer, 0, bytesread - 1);
args.Trim();
string[] arrArgs = args.Split(' ');
mainAppWnd.LaunchNewForm(arrArgs.ToList()); //This line crashes because of a UI Call across threads.
}
在上面的代码中,最后一行由于跨线程的UI调用而崩溃。现在,我明白,我必须以某种方式传递消息到MainAppWnd异步,这样这个新的形式得到启动在它自己的预先存在的上下文中,但我还没有能够这样做。如果是c++,我会简单地做一个::PostMessage()
,它会工作,但在c#中做这个最简单的方法是什么?
假设这是Windows窗体,并且mainAppWnd
是Form
或类似的东西,您可以使用:
Action action = () => mainAppWnd.LaunchNewForm(arrArgs.ToList());
mainAppWnd.BeginInvoke(action);
Control.BeginInvoke
和Control.Invoke
用于在与您调用它们的控件相关的UI线程上执行委托。两者之间的区别在于BeginInvoke
是异步的(触发并忘记),而Invoke
阻塞直到执行委托。