异步事件被触发

问题描述:

我在写一个应用程序,它有多个线程同时运行。每个线程都会与网络服务器通信并下载不同数量的数据。 我想显示应用程序中所有线程的总进度。异步事件被触发

每个线程引发一个事件,每1兆下载:

RaiseEvent My_Event(Size_Downloaded as double,Total_Size as double) 

有显示没有得到横纱误差的主要形式下载的总的方法吗?

它不必是瞬间的,所以计时器可能工作?

+2

没有代码,这个问题有点宽泛。你的意思是什么样的“跨线程错误”?跨线程UI调用?您可以通过使用[Control.Invoke]来避免它们(https://msdn.microsoft.com/de-de/library/a1hetckb%28v=vs.110%29.aspx?cs-save-lang=1&cs-lang= vb#code-snippet-2)在事件处理程序中。 (我不习惯vb语法,所以我没有用完整的代码示例回答)。 –

你可以改变事件的签名,并添加主题 的ID,并使用计时器来显示显示总

Dim _info As New ConcurrentDictionary(Of Integer, DLoadInfo) 

Sub MyEvent(id As Long, Size_Downloaded As Double, Total_Size As Double) 

    Dim v = New DLoadInfo() With 
     { 
      .SizeDownloaded = Size_Downloaded, 
      .TotalSize = Total_Size 
     } 

    _info.AddOrUpdate(id, v, 
      Function(key, oldValue) 
       Return v 
      End Function 
     ) 
End Sub 

Private Sub TimerDisplay_Tick(sender As Object, e As EventArgs) 
    Dim sizeDownloaded, totalSize As double 
    For Each o As DLoadInfo In _info.Values 
     sizeDownloaded += o.SizeDownloaded 
     totalSize += o.TotalSize 
    Next 
    TextBoxSizeDownloaded.Text = sizeDownloaded 
    TextBoxTotalSize.Text = totalSize 
End Sub 

Class DLoadInfo 
    Public property SizeDownloaded As Double 
    Public property TotalSize As Double 
End Class 
+0

这工作完全谢谢 –

正如Rene所说,取决于你得到什么跨线程错误。如果您遇到任何跨线程UI调用错误,那么处理它的最好方法是通过代理。

刚刚撰写了这一个真的很快为例:

这将导致一个跨线程UI错误。

Private Sub DoThis() 
    Dim bgw As New BackgroundWorker 
    AddHandler bgw.DoWork, AddressOf bgwDoWork 
    AddHandler bgw.RunWorkerCompleted, AddressOf bgwDone 

    bgw.RunWorkerAsync(1) 

End Sub 
Private Sub bgwDoWork(sender As Object, e As DoWorkEventArgs) 
    Dim i As Integer = e.Argument 
    RTB.AppendText(CInt(i + 2).ToString) 
End Sub 

然而,委托子,我们就可以在主线程访问控制:

Private Sub DoThis() 
    Dim bgw As New BackgroundWorker 
    AddHandler bgw.DoWork, AddressOf bgwDoWork 
    AddHandler bgw.RunWorkerCompleted, AddressOf bgwDone 

    bgw.RunWorkerAsync(1) 

End Sub 

Private Delegate Sub UpdateText(item As String) 
Private Sub Update_RTB(item As String) 
    If RTB.InvokeRequired Then 
     RTB.Invoke(New UpdateText(AddressOf Update_RTB), item) 
    Else 
     RTB.AppendText(item) 
    End If 
End Sub 

Private Sub bgwDoWork(sender As Object, e As DoWorkEventArgs) 
    Dim i As Integer = e.Argument 
    Update_RTB(CInt(i + 2).ToString) 
End Sub 

不要犹豫,让我知道如果你需要我的任何进一步澄清这一点。

干杯。

+1

谢谢你会尝试这个明天 –

这是一个相当简单的解决方案,我用多线程事件:

Private Sub ThreadSafeRaise_MyEvent(Size_Downloaded As Double, Total_Size As Double) 
    If Me.InvokeRequired = True Then 
     Me.Invoke(Sub() ThreadSafeRaise_MyEvent(Size_Downloaded, Total_Size)) 
    Else 
     RaiseEvent My_Event(Size_Downloaded, Total_Size) 
    End If 
End Sub 

如果需要调用表单(该代码中的Me),该方法使用lambda来调用它,然后再次执行该方法。但是这次当表单已被调用时,事件可以正常提升。

为了提高你只需要调用(不< >)事件:

ThreadSafeRaise_MyEvent(<size downloaded here>, <total size here>) 

就是这样!不需要进一步的调用,以这种方式提升事件是线程安全的。您也不需要声明自己的任何代表,因为lambda(Sub()表达式)可以为您做。

希望这会有所帮助!