2015-12-02 106 views
4

我在寫一個應用程序,它有多個線程同時運行。每個線程都會與網絡服務器通信並下載不同數量的數據。 我想顯示應用程序中所有線程的總進度。異步事件被觸發

每個線程引發一個事件,每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語法,所以我沒有用完整的代碼示例回答)。 –

回答

3

你可以改變事件的簽名,並添加主題 的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

這工作完全謝謝 –

3

正如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

謝謝你會嘗試這個明天 –

2

這是一個相當簡單的解決方案,我用多線程事件:

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()表達式)可以爲您做。

希望這會有所幫助!