.NET 如何定义异步任务回调
.NET How to define an Async task Callback
我正在将我的代码从 BackgroundWorker 更新到 Tasks,运行 遇到了问题。我想模仿 BackgroundWorker 的功能,当 DoWork()
线程完成时,BackgroundWorker 调用 DoWorkCompleted()
函数。这是我目前拥有的:
Private Sub btn_Start_Click(sender, e) Handles btn_Start.Click
btn_Stop.IsEnabled = True
btn_Start.IsEnabled = False
_cts = New CancellationTokenSource()
Dim theWork As Task = Worker.Start(_cts.Token)
theWork.ContinueWith(AddressOf OnWorkCompleted)
End Sub
Private Sub OnWorkCompleted()
btn_Stop.IsEnabled = False
btn_Start.IsEnabled = True
End Sub
Private Sub btn_Stop_Click(sender, e) Handles btn_Stop.Click
_cts.Cancel()
End Sub
然后在另一个文件 Worker.vb 中,我有以下内容:
Private Shared _cts As CancellationToken
Public Shared Function Start(token As CancellationToken) As Task
Try
_cts = token
Return Task.Run(AddressOf Process, token)
Catch ex As TaskCanceledException
MessageBox.Show("Task cancelled")
Return Task.CompletedTask
End Try
End Function
Private Shared Async Sub Process()
Try
Log.Information("0")
Await Task.Delay(1000, _cts)
Log.Information("1")
Await Task.Delay(1000, _cts)
Log.Information("2")
Await Task.Delay(1000, _cts)
Log.Information("3")
Await Task.Delay(1000, _cts)
Log.Information("4")
Await Task.Delay(1000, _cts)
Catch ex As OperationCanceledException
MessageBox.Show("cancelled operation")
End Try
End Sub
差不多,我想要用这段代码发生的事情是模仿当我将它迁移过来时完整代码会发生什么:在用户点击开始后,一个长时间的操作在一个单独的线程上运行并且 UI 仍然有响应。如果用户在任何时候单击停止,任务将结束并调用 OnWorkCompleted
函数。会发生什么情况,是立即调用 OnWorkCompleted() 而不是在单击“停止”时调用。
一般来说,您应该 avoid Async Sub
:
Private Shared Async Function Process() As Task
此外,使用 Await
而不是 ContinueWith
:
Private Async Sub btn_Start_Click(sender, e) Handles btn_Start.Click
btn_Stop.IsEnabled = True
btn_Start.IsEnabled = False
_cts = New CancellationTokenSource()
Try
Await Worker.Start(_cts.Token)
Finally
OnWorkCompleted()
End Try
End Sub
您可能会发现我关于 replacing BackgroundWorker
with Task.Run
的博客 post 系列对您有所帮助。
我正在将我的代码从 BackgroundWorker 更新到 Tasks,运行 遇到了问题。我想模仿 BackgroundWorker 的功能,当 DoWork()
线程完成时,BackgroundWorker 调用 DoWorkCompleted()
函数。这是我目前拥有的:
Private Sub btn_Start_Click(sender, e) Handles btn_Start.Click
btn_Stop.IsEnabled = True
btn_Start.IsEnabled = False
_cts = New CancellationTokenSource()
Dim theWork As Task = Worker.Start(_cts.Token)
theWork.ContinueWith(AddressOf OnWorkCompleted)
End Sub
Private Sub OnWorkCompleted()
btn_Stop.IsEnabled = False
btn_Start.IsEnabled = True
End Sub
Private Sub btn_Stop_Click(sender, e) Handles btn_Stop.Click
_cts.Cancel()
End Sub
然后在另一个文件 Worker.vb 中,我有以下内容:
Private Shared _cts As CancellationToken
Public Shared Function Start(token As CancellationToken) As Task
Try
_cts = token
Return Task.Run(AddressOf Process, token)
Catch ex As TaskCanceledException
MessageBox.Show("Task cancelled")
Return Task.CompletedTask
End Try
End Function
Private Shared Async Sub Process()
Try
Log.Information("0")
Await Task.Delay(1000, _cts)
Log.Information("1")
Await Task.Delay(1000, _cts)
Log.Information("2")
Await Task.Delay(1000, _cts)
Log.Information("3")
Await Task.Delay(1000, _cts)
Log.Information("4")
Await Task.Delay(1000, _cts)
Catch ex As OperationCanceledException
MessageBox.Show("cancelled operation")
End Try
End Sub
差不多,我想要用这段代码发生的事情是模仿当我将它迁移过来时完整代码会发生什么:在用户点击开始后,一个长时间的操作在一个单独的线程上运行并且 UI 仍然有响应。如果用户在任何时候单击停止,任务将结束并调用 OnWorkCompleted
函数。会发生什么情况,是立即调用 OnWorkCompleted() 而不是在单击“停止”时调用。
一般来说,您应该 avoid Async Sub
:
Private Shared Async Function Process() As Task
此外,使用 Await
而不是 ContinueWith
:
Private Async Sub btn_Start_Click(sender, e) Handles btn_Start.Click
btn_Stop.IsEnabled = True
btn_Start.IsEnabled = False
_cts = New CancellationTokenSource()
Try
Await Worker.Start(_cts.Token)
Finally
OnWorkCompleted()
End Try
End Sub
您可能会发现我关于 replacing BackgroundWorker
with Task.Run
的博客 post 系列对您有所帮助。