意外的跨线程问题

3
我试图做一些非常简单的事情,但我一直遇到“跨线程异常”,这让我感到困惑,因为我并没有打算使用多个线程。
我有一个Windows窗体应用程序。它启动另一个Windows窗体应用程序(使用“System.Diagnostics.Process”类),并在关闭该应用程序时捕获Exited事件。然后,我的应用程序事件处理程序尝试将文本从剪贴板复制到当前显示表单上的控件。此时会抛出“跨线程异常”。
我认为问题是来自关闭应用程序的事件在另一个线程中(我在我的舒适区之外,所以请见谅),因此问题归结为“如何防止此异常?”。
我有些约束需要从剪贴板复制,但如果可以解决问题,我可以以不同的方式启动其他应用程序。

1
来点代码怎么样? ;o) - DHN
@DHN 这是一个非常简单的问题,有一个非常直接的解决方案,不会因为具体情况而有所不同;我不认为需要任何额外的代码。 - Servy
1个回答

5
Exited事件不会在UI线程中触发,而是在由Process类创建的某个后台线程中触发以监视其他进程。
为访问控件需要在UI线程上进行调用,可以使用Control.Invoke方法来完成:
textbox1.Invoke(new Action(()=> textbox1.Text = Process.ExitCode.ToString()));

我正在访问调用应用程序中的控件。这是你的意思吗? - haughtonomous
@haughtonomous 分配的文本是无关紧要的;我只是为了举例子而选择了一些内容。正如我在答案中所说,跨线程异常是因为Process类在另一个线程中触发了事件。你没有显式地创建新线程并不能阻止Process类在内部这样做。对于事件处理程序,你附加事件的线程是无关紧要的,它会在类本身选择的任何线程中触发它,并且它没有选择使用UI线程。 - Servy
好的,我明白了。有没有其他方法可以启动从应用程序而不创建另一个线程?在我的主应用程序中,由于遗留代码的封装问题,使您的解决方案在我的情况下相当难以实现(实际的窗体控件被包装在接口背后的其他对象中等等)。 - haughtonomous
@haughtonomous 那么你最终只会将这段代码向下移动。 与在“Exited”事件的事件处理程序中调用UI线程不同,您需要在接口链到达其第一个UI元素时立即调用UI线程。 如果没有更多了解,我将无法提供示例。 否则,没有有效的方法可以不启动另一个线程。 如果您没有启动另一个线程,则会阻塞UI线程,并且应用程序将在进程完成之前冻结。 另一个线程是必需的。 - Servy
1
@Xantham Invoke 会在内部执行检查,所以我不知道为什么这种结构如此常见。它无谓地增加了额外的代码,却没有任何额外的好处。 - Servy
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接