1

我正在创建一个 BackgroundWorker,在它的 DoWork 函数中我有以下代码:

        foreach (string newFilepath in newFilesPath)
        {
                        if (!File.Exists(encryptedFilePath))
                        {
                            encryptedFiles.Add(encryptedFilePath);
                            Helper.SendErrorMail(null, "Could not find encrypted file.", encryptedFilePath);
                            Application.Exit();
                        }
                        else
                        {
                            Helper.Count_DataFeeds++;
                            File.Delete(newFilepath);
                        }
        }

根据此代码,我应该只看到一封邮件,因为应用程序存在,但是我看到了 8 封邮件(对于它正在迭代的每个文件)。为什么应用程序不退出?我想立即杀死该应用程序。

它是一个控制台应用程序。

4

3 回答 3

2

它是一个控制台应用程序

这意味着 Application.Exit() 将不起作用,它只会关闭打开的 Winform 表单。副作用是关闭主窗体会导致消息循环退出。它完成了 Application.Run() 调用,它完成了 Main() 方法并终止了应用程序。

控制台模式应用程序没有任何窗口,也没有消息循环。您应该改用 Environment.Exit() 。

于 2012-11-07T21:52:34.353 回答
1

您需要从对消息泵的基本了解开始。UI 线程是什么,在某个非常低的级别上,是一个 while 循环:

while(!shouldQuitapplication)
{
   Item nextItem = queue.GetNextItem();
   nextItem.Run();
}

每次调用Control.Invoke时,都会向队列中添加一个新项目,每次钩子触发事件(鼠标移动、按钮单击等)时,它都会向队列中添加一个新项目。所有项目都是按照收到的顺序同步处理的。

Application.Exit本质上是一种在队列中所有现有项目完成后结束整个过程的方式。

因为你有一个 BackgroundWorker 正在运行,除了 UI 线程正在做的任何事情之外,它还在做“其他事情”。当您告诉 UI 线程退出时,将需要一些时间来完成队列中的剩余任务。(这就是您看到后台任务执行更多操作的原因;这个数字可能会有所不同。)

请注意,一旦没有更多的非后台线程,整个进程就会被拆除。UI 线程是非后台线程,而您使用的 BackgroundWorker 使用后台线程。当 UI 线程结束时,后台工作程序将停止。如果您手动创建非 UI 线程,那么它可能会保持进程“启动”并且即使在 UI 线程停止后它也不会停止。(虽然这将是一个倒退,所以很明显这在这种情况下没有帮助。)

Application.Exit正如另一个答案中提到的那样,解决方案是通过调用break,return或只是以不同的方式构造循环以使其在无效项目上停止,以确保后台任务在您调用后不做任何事情。

于 2012-11-07T21:01:05.907 回答
0

Environment.Exit 是需要的。

于 2012-11-07T20:57:21.300 回答