使用FileStream的异步文件I/O正在阻止WPF上的UI线程
我试图从一个文件夹复制到另一个文件夹,在msdn之后,我试图在我的WPF应用程序上实现asnyc调用。但我不确定我做错了什么,因为它阻塞了UI线程,我不认为第一个示例是asnyc 这是我的密码使用FileStream的异步文件I/O正在阻止WPF上的UI线程,wpf,vb.net,async-await,Wpf,Vb.net,Async Await,我试图从一个文件夹复制到另一个文件夹,在msdn之后,我试图在我的WPF应用程序上实现asnyc调用。但我不确定我做错了什么,因为它阻塞了UI线程,我不认为第一个示例是asnyc 这是我的密码 Dim tasks = myImages.Select(Async Function(x) Dim result As Image
Dim tasks = myImages.Select(Async Function(x)
Dim result As Image
Try
result = Await CopyImage(x, If(cts IsNot Nothing, cts.Token, Nothing))
Catch ex2 As Exception
End Try
ProgressValue += 1
CompletedText = ProgressValue.ToString() & " of " + MaxValue.ToString() & " images completed."
Return result
End Function)
Dim results = Await Task.WhenAll(tasks)
Public Async Function CopyImage(Image As Image, ct As CancellationToken) As Task(Of Image)
If ct.IsCancellationRequested Then
Return Nothing
End If
Await _mutex.WaitAsync()
Dim SourceMainDirectory As String = "\\Server\Folder1"
Dim DestinationMainDirectory As String = = "\\Server\Folder2"
Dim Path = Image.Path.Replace("/", "\")
Dim Data As String() = Path.Split("\")
Dim Folder As String
Dim ImageName As String
If Data IsNot Nothing AndAlso Data.Length > 1 Then
Folder = Data(0)
ImageName = Data(1)
End If
Dim ImgFullSource = SourceMainDirectory + Folder + "\" + ImageName
Dim ImgFullDest = DestinationMainDirectory + Folder + "\" + ImageName
Try
Using SourceStream As FileStream = File.Open(ImgFullSource, FileMode.Open)
Using DestinationStream As FileStream = File.Create(ImgFullDest)
Await SourceStream.CopyToAsync(DestinationStream, 81920, ct)
Return Image
End Using
End Using
Catch ex As OperationCanceledException
Return Nothing
Catch ex As Exception
Return Nothing
Finally
_mutex.Release()
End Try
Return Nothing
End Function
上面的ProgressValue被提升以更新我的progressbar值。例如,如果我使用myHttpClient.GetAsync方法在web上验证相同的图像,那么这段代码在不阻塞UI线程的情况下运行良好,并且可以完美地异步更新进度
Dim tasks = myImages.Select(Async Function(x)
Dim result As Image
Try
result = Await testUrl_async_cancel(x, If(cts IsNot Nothing, cts.Token, Nothing))
Catch ex2 As Exception
End Try
ProgressValue += 1
CompletedText = ProgressValue.ToString() & " of " + MaxValue.ToString() & " images completed."
Return result
End Function)
Dim results = Await Task.WhenAll(tasks)
Async Function testUrl_async_cancel( ByVal myImage As Image, ByVal ct As CancellationToken) As Task(Of AEL)
If ct.IsCancellationRequested Then
Return Nothing
End If
Await _mutex.WaitAsync()
Dim myHttpClient As New HttpClient()
Dim myHttpResponse As HttpResponseMessage
myHttpClient.BaseAddress = New Uri(imageUrlD)
Try
myHttpResponse = Await myHttpClient.GetAsync(myImageUrl, ct)
Catch ex As OperationCanceledException
myHttpResponse = Nothing
Catch ex As Exception
myHttpResponse = Nothing
Finally
_mutex.Release()
End Try
If myHttpResponse IsNot Nothing AndAlso myHttpResponse.IsSuccessStatusCode Then
Return Nothing
Else
Return myImage
End If
End Function
因此,这应该与CopyImage函数和分别使用sourcestream有关,因为阻止UI线程的所有其他代码都是相同的。如何使这段代码异步,从而不会阻塞WPF上的UI线程?此行为是由于文件流中存在异常。File.Open和File.Create只能返回同步文件流
要获得真正的异步文件流,必须对isAsync参数使用和pass true,或者在options参数中包含FileOptions.asynchronous标志。您必须使用isAsync或options调用构造函数重载,否则文件流将是同步的。基于Stephen Cleary的回答。我更改了filestream读写部分,如下所示,它可以异步工作,而不会阻塞UI线程。我希望这能帮助其他寻求相同解决方案的人 最后一个参数True是Stephen提到的异步参数
Using SourceStream As FileStream = New FileStream(ImgFullSource, FileMode.Open, FileAccess.Read, FileShare.Read, 81920, True)
Using DestinationStream As FileStream = New FileStream(ImgFullDest, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite, 81920, True)
Await SourceStream.CopyToAsync(DestinationStream, 81920, ct)
Return Image
End Using
End Using
厉害。它就像一个符咒。我接受您的答案,并将我的代码更改添加为下面的答案。谢谢