C# 如何从控制台应用程序正确关闭winforms应用程序
我想从控制台应用程序正确关闭winform应用程序。所以我试着这样做:C# 如何从控制台应用程序正确关闭winforms应用程序,c#,winforms,task-parallel-library,C#,Winforms,Task Parallel Library,我想从控制台应用程序正确关闭winform应用程序。所以我试着这样做: var cancelSource = new CancellationTokenSource(); if (runUI) { var UI = new FormUI(somedata); //cancel request if form is clo
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);
}
var data = new Data(...)
var thread = new Thread(() =>
{
data.Execute();
});
thread.Start();
if (runUI)
{
var UI = new FormUI(data);
Application.Run(UI);
}
但当我点击表单上的X按钮时,我得到了空引用异常,我不知道它被抛出到哪里。
那么如何正确地做到这一点呢
更新:
更清楚地说。我的控制台应用程序只是读取用户命令,然后执行一些处理数据的方法。若用户编写显示UI的命令,我希望打开新表单并通过构造函数传递数据。这些数据会更改,因此我每5秒刷新一次表单视图。主要目的是使数据处理独立于表单。但是当我关闭该表单时,会抛出null引用异常。使用取消只是试图在窗体关闭时终止此任务
下面是我的回答:
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);
}
var data = new Data(...)
var thread = new Thread(() =>
{
data.Execute();
});
thread.Start();
if (runUI)
{
var UI = new FormUI(data);
Application.Run(UI);
}
但是当我关闭表单时,它仍然会给我带来错误。我不确定你到底想用取消逻辑等做什么。但是如果你用主线程上的表单来构建你的应用程序,那就相当简单了 尽管表单关闭,_dataThread仍将继续运行
_dataThread = new Thread(MyDataProcessingLoop)
_dataThread.Start()
if(runUI){
_uiForm = new UIForm();
Application.Run(_uiForm);
}else{
Application.Run(); //Keep the application running
}
我不确定你到底想用取消逻辑做什么,但是如果你用主线程上的表单来构建你的应用程序,那就很简单了 尽管表单关闭,_dataThread仍将继续运行
_dataThread = new Thread(MyDataProcessingLoop)
_dataThread.Start()
if(runUI){
_uiForm = new UIForm();
Application.Run(_uiForm);
}else{
Application.Run(); //Keep the application running
}
您的UI表单正在主线程上创建,但随后您在另一个线程上启动了消息循环。表单的创建及其消息循环应在同一线程上。如果您的UI表单退出,则Application.Run消息循环也将退出,因此您的线程也将退出。我不明白你为什么需要取消令牌。如果您让我们知道您的主线程正在做什么,我们可以为您提供一些关于如何在ui窗体关闭时使其退出的指针。控制台应用程序通过构造函数将数据传递到此窗体。表单仅每5秒刷新一次数据并显示它。我建议您只需交换线程。当程序启动时,启动数据线程。然后在主程序线程上调用Application.Run(UI)。如果数据线程被设置为后台线程,那么它将在ui退出时自动退出。但是我不想在ui退出时退出数据线程。UI仅显示数据。因此,当我退出UI时,我希望数据处理仍在进行。您必须显示堆栈跟踪,以提供NRE发生的提示。然而,起点非常糟糕,任务类使用的线程基本上无法显示UI。它必须是正确的线程,必须调用其SetApartmentState()来选择STA。而且它需要用于显示所有UI,如果SystemEvents类开始在错误的线程上引发事件,略过它会给您带来巨大的麻烦。试图在非GUI程序上附加UI永远不会正常工作。您的UI窗体是在主线程上创建的,但随后您在另一个线程上启动了消息循环。表单的创建及其消息循环应在同一线程上。如果您的UI表单退出,则Application.Run消息循环也将退出,因此您的线程也将退出。我不明白你为什么需要取消令牌。如果您让我们知道您的主线程正在做什么,我们可以为您提供一些关于如何在ui窗体关闭时使其退出的指针。控制台应用程序通过构造函数将数据传递到此窗体。表单仅每5秒刷新一次数据并显示它。我建议您只需交换线程。当程序启动时,启动数据线程。然后在主程序线程上调用Application.Run(UI)。如果数据线程被设置为后台线程,那么它将在ui退出时自动退出。但是我不想在ui退出时退出数据线程。UI仅显示数据。因此,当我退出UI时,我希望数据处理仍在进行。您必须显示堆栈跟踪,以提供NRE发生的提示。然而,起点非常糟糕,任务类使用的线程基本上无法显示UI。它必须是正确的线程,必须调用其SetApartmentState()来选择STA。而且它需要用于显示所有UI,如果SystemEvents类开始在错误的线程上引发事件,略过它会给您带来巨大的麻烦。试图在一个非GUI程序上嵌入UI永远不会奏效。为了更清楚,我更新了帖子。我尝试了您的解决方案,但仍然给我空引用异常。请确保选中“调试->异常->Clr异常->抛出”。每当发生异常时,这将停止执行。检查堆栈轨迹。问题不在于表单的关闭,而是表单在退出时所做的事情,退出后计时器仍在试图修改表单,应用程序在关闭后试图与表单交互。另外,你应该在你的应用程序中实现一些日志记录,这样你就不需要做这种猜测工作了。你是对的。感谢您让我知道如何检查此异常。问题是,我试图在关闭表单后对一些不再存在的东西进行操作。没问题,很高兴我能提供帮助。我更新了帖子,使其更加清晰。我尝试了您的解决方案,但仍然给我空引用异常。请确保选中“调试->异常->Clr异常->抛出”。每当发生异常时,这将停止执行。检查堆栈轨迹。问题不在于表单的关闭,而是表单在退出时所做的事情,退出后计时器仍在试图修改表单,应用程序在关闭后试图与表单交互。另外,你应该在你的应用程序中实现一些日志记录,这样你就不需要做这种猜测工作了。你是对的。感谢您让我知道如何检查此异常。问题是我试图在关闭表单后对一些不存在的东西进行操作。没问题,很高兴我能帮上忙。