情况如下:
我有一个创建主表单的类。它将主Form的创建对象保持为静态成员,如下所示:
public static mainAppWnd;
并在main
代码中的某处创建表单,如下所示:
mainAppWnd = new MainAppWnd();
现在,我必须一次打开这个应用程序的一个实例,我通过Mutex这样做。那部分工作正常。当打开该应用程序的第二个实例时,我必须检查它是否包含一些命令行参数。如果是这样,我必须将这些命令行args传递给现有的运行实例,并且在该运行实例中,我必须打开一个新表单。这个新表单的开头将在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#中最简单的方法是什么?
答案 0 :(得分:2)
假设这是Windows窗体,并且mainAppWnd
是Form
或类似的东西,您可以使用:
Action action = () => mainAppWnd.LaunchNewForm(arrArgs.ToList());
mainAppWnd.BeginInvoke(action);
Control.BeginInvoke
和Control.Invoke
用于在与您调用它们的控件关联的UI线程上执行委托。两者之间的区别在于BeginInvoke
是异步的(一劳永逸),而Invoke
会阻塞,直到委托被执行为止。