Вам нужно, чтобы поток пользовательского интерфейса вызывал метод frmMain.refreshStats. Существует, конечно, много способов сделать это, используя свойство Control.InvokeRequired и Control.Invoke ( Документация MSDN ).
Вы можете либо сделать так, чтобы метод "EndAsync" сделал поток пользовательского интерфейса безопасным для вызова метода, либо иметь метод refreshStats для проверки безопасности потока (с помощью Control.InvokeRequired).
Потокобезопасный пользовательский интерфейс EndAsync будет выглядеть примерно так:
Public Delegate Sub Method(Of T1, T2)(ByVal arg1 As T1, ByVal arg2 As T2)
Sub skDataReceived(ByVal result As IAsyncResult)
Dim frmMain As Form = CType(My.Application.OpenForms.Item("frmMain"), frmMain)
Dim d As Method(Of Object, Object)
'create a generic delegate pointing to the refreshStats method
d = New Method(Of Object, Object)(AddressOf frmMain.refreshStats)
'invoke the delegate under the UI thread
frmMain.Invoke(d, New Object() {d1, d2})
End Sub
Или вы можете проверить метод refreshStats, чтобы увидеть, нужно ли ему вызываться из потока пользовательского интерфейса:
Public Delegate Sub Method(Of T1, T2)(ByVal arg1 As T1, ByVal arg2 As T2)
Sub refreshStats(ByVal d1 As Object, ByVal d2 As Object)
'check to see if current thread is the UI thread
If (Me.InvokeRequired = True) Then
Dim d As Method(Of Object, Object)
'create a delegate pointing to itself
d = New Method(Of Object, Object)(AddressOf Me.refreshStats)
'then invoke itself under the UI thread
Me.Invoke(d, New Object() {d1, d2})
Else
'actual code that requires UI thread safety goes here
End If
End Sub