【发布时间】:2016-08-11 08:07:37
【问题描述】:
我想从控制台应用程序中正确关闭 winform 应用程序。所以我尝试这样的事情:
var cancelSource = new CancellationTokenSource();
if (runUI)
{
var UI = new FormUI(somedata);
//cancel request if form is closing.
UI.FormClosing += (sender, args) =>
{
cancelSource.Cancel();
};
Task.Factory.StartNew(() =>
{
//run form from console app.
Application.Run(UI);
}, cancelSource.Token);
}
但是当我单击表单上的 X 按钮时,我得到了空引用异常,我不知道它是在哪里抛出的。 那么如何正确地做呢?
更新: 要更清楚。我的控制台应用程序只是读取用户命令,然后执行一些处理数据的方法。如果用户编写命令来显示 UI,我想打开新表单并通过构造函数传递数据。这些数据会发生变化,因此我每 5 秒刷新一次此表单视图。主要目的是使数据处理独立于表格。但是当我关闭该表单时,会引发空引用异常。使用取消只是试图在表单关闭时终止此任务。
在回答之后我做了这样的事情:
var data = new Data(...)
var thread = new Thread(() =>
{
data.Execute();
});
thread.Start();
if (runUI)
{
var UI = new FormUI(data);
Application.Run(UI);
}
但是当我关闭表单时它仍然给我错误。
【问题讨论】:
-
您的 UI 表单正在主线程上创建,但随后您在另一个线程上启动了消息循环。表单及其消息循环的创建应该在同一个线程上。如果您的 UI 表单退出,那么 Application.Run 消息循环也将退出,因此您的线程也将退出。我不明白您为什么需要取消令牌。如果您让我们知道您的主线程在做什么,我们可以为您提供一些关于如何在 ui 表单关闭时退出的指示。
-
控制台应用程序通过构造函数将数据传递给此表单。表单仅每 5 秒刷新一次数据并显示。
-
我建议您简单地交换线程。当程序启动时启动你的数据线程。然后在主程序线程上调用 Application.Run(UI)。如果数据线程设置为后台线程,那么它会在 ui 时自动退出。
-
但我不想在 ui 退出时退出数据线程。 UI 只显示数据。因此,当我退出 UI 时,我希望数据处理仍在进行中。
-
您必须显示堆栈跟踪以提供发生 NRE 的提示。然而,起点非常糟糕,Task 类使用的线程根本无法显示 UI。它必须是一个合适的线程,必须调用它的 SetApartmentState() 来选择 STA。并且它需要用于显示 all UI,当 SystemEvents 类开始在错误的线程上引发事件时,忽略它会给您带来巨大的麻烦。尝试在非 GUI 程序上附加 UI 永远不会奏效。
标签: c# winforms task-parallel-library