确保异步任务在 vb.net 应用程序终止之前完成

Making sure async tasks complete before vb.net application terminates

我正在创建一个 vb.net 桌面应用程序。此应用程序包括一些异步功能。当用户通过右上角的红色 X 关闭应用程序时,可能 运行 这些异步功能中的一个或多个有一些逻辑。问题是,程序在它们完成之前就终止了。我认为在通话中使用 "Await" 可以做到这一点,但显然不是。

我找到了 this thread that talks about using ManualResetEvent,但我无法理解所有内容,尤其是因为问题是在控制台应用程序的上下文中,而答案链接到的 MSDN 文档是关于指定线程的,不仅仅是使用异步任务。作为无论如何使用它的尝试,我尝试将其添加到我的主窗体中:

Public resetEvent As ManualResetEvent = New ManualResetEvent(False)

在调用其中一个函数之后,我立即添加了这个(引用包括调用):

Await activeCount.SerializeAsync(activeCount)
resetEvent.WaitOne()

在我的异步函数本身的末尾,在返回任务之前,添加了这个:

frmMain.resetEvent.Set()

不过,我认为我没有正确使用它。程序仍然在完成之前终止。

甚至在那之前,我认为这种东西的最佳位置是 ApplicationEvents MyApplication_Shutdown,但我不确定如何知道这样的功能是否仍然 运行ning点.

那么在这种情况下确保我的所有异步函数在应用程序终止之前完成的最佳方法是什么?

谢谢!


接受答案后更新:

虽然 F0r3v3r-A-N00b 的回答有效,但我意识到在某些情况下我需要使用对话框。我无法在后台工作人员中调用它,因为对话框在 GUI 线程上,而不是在后台线程上。我试着四处移动,所以我会先调用对话框,然后让后台工作人员等等,但无论出于何种原因,我都无法让它工作。

长话短说,我通过简单地制作我的函数的同步版本来绕过它,所以我可以说 'if the user terminated the program and I need to call any of these functions before closing, call the synchronous versions instead'。这样可行。谢谢!

试试这个。创建一个新项目。向您的表单添加 1 个标签和后台工作人员。将此粘贴到表单的代码区域:

Public Class Form1
Dim taskCompleted As Boolean = False
Dim taskIsrunning As Boolean = False

Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    Threading.Thread.Sleep(5000)
End Sub






Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    taskCompleted = True
    taskIsRunning = False
    Label1.Text = "Background task completed."
    Me.Close()
End Sub






Private Sub Form1_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    If taskIsRunning Then
       e.Cancel = True
       Exit Sub
    End If

    If Not taskCompleted Then
        taskIsRunning = True
        Label1.Text = "Starting background task."
        BackgroundWorker1.RunWorkerAsync()
        Label1.Text = "Background task is running."
        e.Cancel = True
    End If
End Sub
End Class