Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从控制台应用程序正确关闭winforms应用程序_C#_Winforms_Task Parallel Library - Fatal编程技术网

C# 如何从控制台应用程序正确关闭winforms应用程序

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

我想从控制台应用程序正确关闭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);
                }
            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异常->抛出”。每当发生异常时,这将停止执行。检查堆栈轨迹。问题不在于表单的关闭,而是表单在退出时所做的事情,退出后计时器仍在试图修改表单,应用程序在关闭后试图与表单交互。另外,你应该在你的应用程序中实现一些日志记录,这样你就不需要做这种猜测工作了。你是对的。感谢您让我知道如何检查此异常。问题是我试图在关闭表单后对一些不存在的东西进行操作。没问题,很高兴我能帮上忙。