|
Public Class CrossThread
Public Shared Sub RunAsync(Of T1, T2, T3)( _
ByVal Action As Action(Of T1, T2, T3), ByVal Arg1 As T1, _
ByVal Arg2 As T2, ByVal Arg3 As T3)
Action.BeginInvoke(Arg1, Arg2, Arg3, _
New AsyncCallback(AddressOf Action.EndInvoke), Nothing)
End Sub
Public Shared Sub RunAsync(Of T1, T2)( _
ByVal Action As Action(Of T1, T2), ByVal Arg1 As T1, ByVal Arg2 As T2)
Action.BeginInvoke(Arg1, Arg2, _
New AsyncCallback(AddressOf Action.EndInvoke), Nothing)
End Sub
Public Shared Sub RunAsync(Of T1)(ByVal Action As Action(Of T1), _
ByVal Arg1 As T1)
Action.BeginInvoke(Arg1, _
New AsyncCallback(AddressOf Action.EndInvoke), Nothing)
End Sub
Public Shared Sub RunAsync(ByVal Action As Action)
Action.BeginInvoke(New AsyncCallback(AddressOf Action.EndInvoke), _
Nothing)
End Sub
Private Shared Function GuiCrossInvoke(ByVal Action As [Delegate], _
ByVal ParamArray Args() As Object) As Boolean
If Application.OpenForms.Count = 0 Then
Return True
End If
If Application.OpenForms(0).InvokeRequired Then
Application.OpenForms(0).BeginInvoke(Action, Args)
Return True
End If
End Function
Public Shared Sub RunGui(Of T1, T2, T3)( _
ByVal Action As Action(Of T1, T2, T3), ByVal Arg1 As T1, _
ByVal Arg2 As T2, ByVal Arg3 As T3)
If Not GuiCrossInvoke(Action, Arg1, Arg2, Arg3) Then _
Action(Arg1, Arg2, Arg3)
End Sub
Public Shared Sub RunGui(Of T1, T2)(ByVal Action As Action(Of T1, T2), _
ByVal Arg1 As T1, ByVal Arg2 As T2)
If Not GuiCrossInvoke(Action, Arg1, Arg2) Then Action(Arg1, Arg2)
End Sub
Public Shared Sub RunGui(Of T1)(ByVal Action As Action(Of T1), _
ByVal Arg1 As T1)
If Not GuiCrossInvoke(Action, Arg1) Then Action(Arg1)
End Sub
Public Shared Sub RunGui(ByVal Action As Action)
If Not GuiCrossInvoke(Action) Then Action()
End Sub
End Class
Imports System.IO
Public Class frmAsyncStreaming
Private Const _Output As String = "Output"
Private Const _Src As String = "Output\TestSource.Data"
Private Const _Dest As String = "Output\TestDest"
Private Sub CreateTestSource()
Me.RichTextBox1.AppendText("erstelle TestSource - bitte warten" & _
Lf & Lf)
Me.RichTextBox1.Refresh()
If Not Directory.Exists(_Output) Then Directory.CreateDirectory(_Output)
Diagnostics.Process.Start(_Output)
Using _
Reader As New FileStream(Application.ExecutablePath, _
FileMode.Open, FileAccess.Read), _
Writer As New FileStream(_Src, FileMode.Create)
For I As Integer = 0 To 999
Reader.Position = 0
StreamX.WriteTo(Reader, Writer)
Next
End Using
End Sub
Private Sub Button_Click(ByVal sender As Object, ByVal e As EventArgs) _
Handles btStreamBegin.Click, btDelegatBegin.Click, _
btExplicitThread.Click, btCopySynchron.Click, btBackgroundworker.Click
Static ID As Integer
ID += 1
Dim Dest As String = _Dest & ID
Dim Cause As String = ""
Dim sFormat As String = "{0,-14:HH:mm:ss.FFF} starte {1} -> {2}"
If Not File.Exists(_Src) Then CreateTestSource()
Select Case True
Case sender Is btStreamBegin
Dest &= ".StreamBeginRead"
Cause = "Stream.BeginRead()"
CopyFileMS(_Src, Dest)
Case sender Is btDelegatBegin
Cause = "Delegate-Invoking"
Dest &= ".Invoking"
CrossThread.RunAsync(AddressOf CopyFile, Cause, _Src, Dest)
Case sender Is btExplicitThread
Cause = "explicit Threading"
Dest &= ".Threading"
Dim Tr As New Threading.Thread( _
AddressOf ExplicitThreadStart)
Tr.Start(New String() {Cause, _Src, Dest})
Case sender Is btBackgroundworker
Dest &= ".Backgroundworker"
If BackgroundWorker1.IsBusy Then
Cause = "BackgroundWorker1.IsBusy = True " & _
"- Kann grad nicht"
Exit Select
End If
Cause = "Backgroundworker"
BackgroundWorker1.RunWorkerAsync(New String() _
{Cause, _Src, Dest})
Case sender Is btCopySynchron
Cause = "synchrones kopieren"
Dest &= ".Synchron"
WriteLine(String.Format(sFormat, Now, _
Cause, Path.GetFileName(Dest)))
CopyFile(Cause, _Src, Dest)
Return
End Select
WriteLine(String.Format(sFormat, Now, Cause, Path.GetFileName(Dest)))
End Sub
Private Sub ExplicitThreadStart(ByVal Obj As Object)
Dim Args As String() = DirectCast(Obj, String())
CopyFile(Args(0), Args(1), Args(2))
End Sub
Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, _
ByVal e As System.ComponentModel.DoWorkEventArgs) _
Handles BackgroundWorker1.DoWork
Dim Args As String() = DirectCast(e.Argument, String())
CopyFile(Args(0), Args(1), Args(2))
End Sub
Private Sub CopyFile(ByVal Cause As String, ByVal Src As String, _
ByVal Dest As String)
Using Reader As New FileStream(Src, _
FileMode.Open, FileAccess.Read, FileShare.Read), _
Writer As New FileStream(Dest, FileMode.Create)
StreamX.WriteTo(Reader, Writer)
End Using
WriteLine(String.Format("{0,-14:HH:mm:ss.FFF} beende {1} ({2})", _
Now, Cause, Path.GetFileName(Dest)))
End Sub
Private Sub WriteLine(ByVal Text As String)
CrossThread.RunGui(AddressOf Me.RichTextBox1.AppendText, Text & Lf)
End Sub
#Region "Asynchroner Kopiervorgang in der von MS vorgesehenen Umständlichkeit"
Private Structure AsyncInfo
Public Reader As Stream
Public Buffer As Byte()
Public WriterName As String
Public Sub New(ByVal Reader As Stream, _
ByVal Buffer As Byte(), ByVal WriterName As String)
Me.Reader = Reader
Me.Buffer = Buffer
Me.WriterName = WriterName
End Sub
End Structure
Private Sub CopyFileMS(ByVal Src As String, ByVal Dest As String)
Dim Buf(Short.MaxValue - 1) As Byte
Dim Reader As New FileStream( _
Src, FileMode.Open, FileAccess.Read, FileShare.Read, _
Buf.Length, FileOptions.Asynchronous)
Reader.BeginRead( _
Buf, 0, Buf.Length, AddressOf Callback, _
New AsyncInfo(Reader, Buf, Dest))
End Sub
Private Sub Callback(ByVal Ar As IAsyncResult)
With DirectCast(Ar.AsyncState, AsyncInfo)
Using Reader As Stream = _
.Reader, Writer As New FileStream(.WriterName, FileMode.Create)
Dim Portion As Integer = Reader.EndRead(Ar)
Writer.Write(.Buffer, 0, Portion)
While Portion = .Buffer.Length
Portion = Reader.Read(.Buffer, 0, .Buffer.Length)
Writer.Write(.Buffer, 0, Portion)
End While
End Using
End With
WriteLine(String.Format("{0,-14:HH:mm:ss.FFF} beende " & _
"Stream.EndRead()", Now))
End Sub
#End Region
Private Sub frmAsyncStreaming_FormClosed(ByVal sender As Object, _
ByVal e As FormClosedEventArgs) Handles MyBase.FormClosed
Directory.Delete(_Output, True)
End Sub
End Class
Imports System.Runtime.CompilerServices
Imports System.IO
Public Module StreamX
Public Sub WriteTo( _
ByVal ReadStream As Stream, _
ByVal WriteStream As Stream, _
Optional ByVal Count As Long = Long.MaxValue, _
Optional ByVal Bufsize As Integer = Short.MaxValue)
Dim Buf(Bufsize - 1) As Byte
Dim ReadCount As Long = 0
While Count > ReadCount
Dim Portion As Integer = _
ReadStream.Read(Buf, 0, _
CInt(Math.Min(Count - ReadCount, Bufsize)))
If Portion = 0 Then
If Count = Long.MaxValue Then Return
Throw New ArgumentException(String.Concat( _
"StreamX.WriteTo(ReadStream, WriteStream, Count:=", _
Count, "): ReadStream konnte ", "nur ", ReadCount, _
" Bytes lesen"))
End If
ReadCount += Portion
WriteStream.Write(Buf, 0, Portion)
End While
End Sub
End Module
Namespace System
Public Delegate Sub Action()
Public Delegate Sub Action(Of T1, T2) _
(ByVal Arg1 As T1, ByVal Arg2 As T2)
Public Delegate Sub Action(Of T1, T2, T3) _
(ByVal Arg1 As T1, ByVal Arg2 As T2, ByVal Arg3 As T3)
End Namespace |