【问题标题】:Nth call to backgroundworker spawns N events第 N 次调用 backgroundworker 产生 N 个事件
【发布时间】:2015-06-25 20:52:11
【问题描述】:

我有一个 Sub 每次调用它都会使 backgroundworker 变暗。后台工作人员的 dowork 函数通过包含在连接到服务器的 dll 中的套接字连接代码调用数据。然后,来自服务器的返回被包装在套接字 dll 引发的事件中,并且主 UI 线程上的一个名为 RequestResult(见下文)的事件处理程序进行侦听。当我反复调用带有 backgroundworker 的 sub 时,我从在 RequestResult 上获得一个事件响应触发到多个事件,如下所示:

调用 #1:返回 1 个事件

调用 #2:返回 2 个事件

....

调用 #N:返回 N 个事件

重要的是要注意,在将 backgroundworker 添加到 sub 之前,我没有这种行为。

这是我正在做的简化代码:

Public Sub RequestData(ByVal args As object)

Dim bw As BackgroundWorker = New BackgroundWorker
AddHandler bw.DoWork, AddressOf bw_DoWork
bw.RunWorkerAsync(args)

End Sub

Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)

Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
Dim args As SocketArgs = e.Argument

    RequestServerData(args) 'This calls server thru socket connection dll


End Sub

然后在某个时间点从服务器接收数据并包装在主 UI 线程上的控件侦听的事件中:

'Event handler on the UI thread for event containing serverdata. It fires N times.
Private Sub RequestResult(e As SocketsArgs)
If Not Me.CheckAccess Then
  Dispatcher.Invoke(Sub() Me.RequestResult(e))
  Exit Sub
End If

'Do stuff with data

 End Sub

我觉得我缺少有关 BackGroundWorker 的一些基本知识,即它如何从根本上与线程池一起工作。我不应该每次都重新调整它(即它是一个类级别的变量)吗?它是为每个对 dowork 的调用生成一个线程,还是将它们全部堆叠在一个线程上?我是否需要处理 backgroundworker 以防止触发多个事件?

【问题讨论】:

  • 您能告诉我们(编辑您的帖子)Sub RequestResult 在哪里注册为事件处理程序吗?还有,相关事件是在哪里引发的?
  • 已编辑。 Sub RequestResult 位于 UI 线程上,位于主窗口的代码隐藏中。该事件由 RequestServerData 调用的类中包含的 dll 引发。
  • 对不起,但这并没有回答我的问题。我想查看RequestResult 注册为事件处理程序的实际代码。我想查看AddHandler 调用和调用它的上下文。我还想查看您的套接字 dll 引发事件的代码,该事件导致对RequestResult 的调用(或在本例中为多个调用)。实际上,最好在您的帖子中发布a Minimal, Complete, and Verifiable example,我们可以自己运行以重现您的问题。如果你能做到这一点,你几乎可以保证得到一个好的答案。

标签: vb.net multithreading events event-handling backgroundworker


【解决方案1】:

我遇到了类似的问题(使用 Visual Studio 2015、asp.net、vb),这让我抓狂,但最后我将其范围缩小到我只能称之为 Visual Studio 的无证功能...我有

Dim WithEvents RepWorker as BackgroundWorker

RepWorker = DirectCast(Session("ReportWorker"),Backgroundworker))
if RepWorker is nothing then
    RepWorker = new BackgroundWorker
    AddHandler RepWorker.DoWork, AddressOf RepWorker_MakeReport
    Session("ReportWorker") = RepWorker
end if
RepWorker = DirectCast(Session("ReportWorker"),Backgroundworker))
RepWorker.RunWorker(.....)

后来我有了例行公事

Sub RepWorker_MakeReport(...) handles RepWorker.DoWork
....
End Sub

对 RepWorker_MakeReport 的调用不断增加,即使对 raise 事件的跟踪显示该事件仅被触发一次。

在撕掉我剩下的头发,在不同的段之间移动代码,甚至尝试添加 RemoveHandler 调用之后,我终于完全删除了 AddHandler 并预期一个错误但没有得到一个,而是例程是第一次正确调用一次,但第二次和第三次仍然增加等等。

最后我怀疑它....我从子定义中删除了“句柄 RepWorker.DoWork”,然后突然一切都开始按预期运行。

所以这个故事的寓意是,如果您正在使用 BackgroundWorkers 并且想要可靠地控制事件处理程序,那么您自己定义它们并且不要在子定义之后包含“handles”指令。

祝你好运……

【讨论】:

  • 您所描述的问题似乎与问题无关。具体来说,问题中的代码在DoWork 子定义上没有Handles 子句。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-20
  • 1970-01-01
  • 1970-01-01
  • 2017-04-30
  • 1970-01-01
  • 2012-10-20
相关资源
最近更新 更多