gpt4 book ai didi

vb.net - 想要在不使用 Application.DoEvents 的情况下多次调用同一个 BackgroundWorker

转载 作者:行者123 更新时间:2023-12-01 00:43:18 25 4
gpt4 key购买 nike

我遇到了一个问题,我可以使用 Application.DoEvents 解决这个问题,但我不想留下这个问题,因为它可能会引入各种讨厌的问题。

背景:我们的应用程序主要是一个桌面应用程序,可以多次调用网络服务。我们控制一切,但不会认真考虑对整体系统设计的更改。其中一个调用 Calculate 经常使用,偶尔可能需要几分钟来处理所有数据以返回有效结果。

以前,这个对 Calculate 的调用是同步完成的,因此会阻塞 UI,让用户想知道应用程序是否已卡住,等等。我已经成功地将所有漫长的等待调用移到了 BackgroundWorker,然后做了一个简单的等待屏幕将循环显示“正在计算...”动画消息。

现在,当我们的 UI 代码试图在第一个计算例程完成之前再次调用计算例程时,问题就出现了。我会收到“此 BackgroundWorker 当前正忙,无法运行多个实例...”消息。我认为应该由 resetEvent.WaitOne() 调用控制。它没有,所以我想也许另一个控制对整个例程的访问的事件会有所帮助,所以我添加了 calcDoneEvent。这仍然没有解决问题,但会导致它在第二次调用 Calculate 的 calcDoneEvent.WaitOne() 调用时无限期阻塞。然后一时兴起,我将 Application.DoEvents 添加到 Calculate 和 viola 的底部,问题解决了。

我不想把那个 .DoEvents 留在那儿,因为我读过它会导致以后很难找到的问题。有没有更好的方法来处理这种情况?

提前致谢..

Private WithEvents CalculateBGW As New System.ComponentModel.BackgroundWorker
Dim resetEvent As New Threading.AutoResetEvent(False)
Dim calcDoneEvent As New Threading.AutoResetEvent(True)

Public Sub Calculate()

calcDoneEvent.WaitOne() ' will wait if there is already a calculate running.'
calcDoneEvent.Reset()

' setup variables for the background worker'

CalculateBGW.RunWorkerAsync() ' Start the call to calculate'

Dim nMsgState As Integer = 0
' will block until the backgorundWorker is done'
Do While Not resetEvent.WaitOne(200) ' sleep for 200 miliseconds, then update the status window'
Select Case nMsgState
Case 1
PleaseWait(True, vbNull, "Calculating. ")
Case 2
PleaseWait(True, vbNull, "Calculating.. ")
Case 3
PleaseWait(True, vbNull, "Calculating... ")
Case 4
PleaseWait(True, vbNull, "Calculating....")
Case Else
PleaseWait(True, vbNull, "Calculating ")
End Select
nMsgState = (nMsgState + 1) Mod 5
Loop

PleaseWait(False, vbNull) 'make sure the wait screen goes away'

calcDoneEvent.Set() ' allow another calculate to proceed'
Application.DoEvents() ' I hate using this here'
End Sub

Private Sub CalculateBGW_DoWork(ByVal sender As System.Object, _
ByVal e As System.ComponentModel.DoWorkEventArgs) Handles CalculateBGW.DoWork
Try
'make WS Call, do data processing on it, can take a long time..'
'No Catch inside the DoWork for BGW, or exception handling wont work right...'
'Catch'
Finally
resetEvent.Set() 'unblock the main thread'
End Try
End Sub

Private Sub CalculateBGW_RunWorkerCompleted(ByVal sender As Object, _
ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles CalculateBGW.RunWorkerCompleted

'If an error occurs we must check e.Error prior to touching e.Result, or the BGW'
'will possibly "eat" the exception for breakfast (I hear theyre tasty w/ jam)'
If Not (e.Error Is Nothing) Then

'If a Web Exception timeout, retry the call'
If TypeOf e.Error Is System.Net.WebException And _
e.Error.Message = "The operation has timed out" And _
intRetryCount < intRetryMax Then

' Code for checking retry times, increasing timeout, then possibly recalling the BGW'

resetEvent.Reset()
CalculateBGW.RunWorkerAsync() 'restart the call to the WS'
Else
Throw e.Error ' after intRetryMax times, go ahead and throw the error up higher'
End If
Else
Try

'normal completion stuff'

Catch ex As Exception
Throw
End Try
End If

End Sub

最佳答案

您声明:

Private WithEvents CalculateBGW As New System.ComponentModel.BackgroundWorker
Dim resetEvent As New Threading.AutoResetEvent(False)
Dim calcDoneEvent As New Threading.AutoResetEvent(True)

作为包含类的私有(private)字段。请注意,通过这种方式,对 RunWorkerAsync() 的所有调用都引用 BackgroundWorker 类的相同对象实例(即,引用相同的目的)。这就是它“忙”的原​​因。此代码旨在在给定时间仅容纳一个 BackgroundWorker

如果您想让 UI 代码在需要时调用 Calculate() 方法,您应该在 Calculate() 方法中将 CalculateBGW 声明为局部变量,从而创建一个新实例BackgroundWorker 类的每次调用(它们将异步运行)。这意味着您还必须使用 AddHandlerRemoveHandler 添加和删除 Calculate() 中的事件处理程序。

有几种方法可以根据进度更新 UI,但建议使用 BackgroundWorker.ProgressChanged 事件和 BackgroundWorker.ReportProgress 方法。

使用BackgroundWorker.RunWorkerCompleted事件作为回调触发器,向UI报告计算完成,从而触发需要的代码来表示结果。这种方法消除了维护一个线程循环来控制计算线程的需要 - 从而消除了对 DoEvents() 的需要。它让计算线程在完成工作时通知它的老板,而不是让老板检查 worker 的状态并一遍又一遍地 sleep 。

关于vb.net - 想要在不使用 Application.DoEvents 的情况下多次调用同一个 BackgroundWorker,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2382705/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com