在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#中做这个最简单的方法是什么?

在c#中通过线程调用其他类的事件

假设这是Windows窗体,并且mainAppWndForm或类似的东西,您可以使用:

Action action = () => mainAppWnd.LaunchNewForm(arrArgs.ToList());
mainAppWnd.BeginInvoke(action);

Control.BeginInvokeControl.Invoke用于在与您调用它们的控件相关的UI线程上执行委托。两者之间的区别在于BeginInvoke是异步的(触发并忘记),而Invoke阻塞直到执行委托。