Async CTP v3 - Form is not responding
-
sábado, 24 de diciembre de 2011 9:54
Hi all,
I played around with the new Async CTP v3 and try to list all files and its subdirectories asyncronously and show this progress by using a progress bar.
Most of the code works fine, but just in the moment I list all entries my Windows form is not responding. What I'm doing wrong?
Below my source code:
Greetings
Peter
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
Imports System.Collections.ObjectModel
Imports System.Net
Public Class Form1
Private Async Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
'Clear all entries
Me.ProgressBar1.Value = 0
Me.ListBox1.Items.Clear()
'Define progress
Dim progress As New Progress(Of NumberEntries)
'Define ProgressBar
Me.ProgressBar1.Minimum = 0
Me.ProgressBar1.Maximum = 100
'Handler
AddHandler progress.ProgressChanged, AddressOf ShowProgress
'Call
Await TaskEx.Run(Function() Auflistung("C:\windows", progress))
End Sub
Public Shared Function Auflistung(ByVal dir As String, ByVal progress As IProgress(Of NumberEntries)) As Task(Of String())
Dim Direc As New DirectoryInfo(dir)
Dim Files() As FileInfo
Dim I As Long = 0
Files = Direc.GetFiles("*.*", SearchOption.AllDirectories)
For I = 0 To Files.GetUpperBound(0) - 1
progress.Report(New NumberEntries With {.Count = (I / Files.GetUpperBound(0)), .Eintrag = Files(I).ToString})
Next
End Function
Public Class NumberEntries
Public Count As Long
Public Eintrag As String
End Class
Public Sub ShowProgress(source As Object, e As Object)
Me.ProgressBar1.Value = e.Count * 100
Me.ListBox1.Items.Add(e.eintrag)
End Sub
End Class
- Editado Peter Schirmer sábado, 24 de diciembre de 2011 9:55
Todas las respuestas
-
sábado, 24 de diciembre de 2011 14:35
The reason your form is going (temporarily) unresponsive is because DirectoryInfo.GetFiles does all of the asynchronous work, and then you're doing all of the progress updates all at once. So your UI thread is flooded with updates.
I recommend using DirectoryInfo.EnumerateFiles.
P.S. Read through the Task-based Asynchronous Pattern document - it's in your VS Async CTP install directory under My Documents. It explains how to pattern your asynchronous methods so that they follow best practices and are unsurprising to other programmers.
-Steve
Programming blog: http://nitoprograms.blogspot.com/
Including my TCP/IP .NET Sockets FAQ
and How to Implement IDisposable and Finalizers: 3 Easy Rules
Microsoft Certified Professional Developer
How to get to Heaven according to the Bible- Marcado como respuesta Stephen Toub - MSFTMicrosoft Employee, Moderator sábado, 31 de diciembre de 2011 18:48
-
domingo, 25 de diciembre de 2011 16:22
Hi Steve,
thanks for your hint! Now my Windows form is still responding while all files are listed. Below the whole source code including the changes.
Merry Christmas,
Peter
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
Imports System.Collections.ObjectModel
Imports System.Net
Public Class Form1
Private Async Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
'Clear all entries
Me.ProgressBar1.Value = 0
Me.ListBox1.Items.Clear()
'Define progress
Dim progress As New Progress(Of NumberEntries)
'Define ProgressBar
Me.ProgressBar1.Minimum = 0
Me.ProgressBar1.Maximum = 100
'Handler
AddHandler progress.ProgressChanged, AddressOf ShowProgress
'Call
Await TaskEx.Run(Function() ListInfos("C:\windows", progress))
End Sub
Public Shared Function ListInfos(ByVal dir As String, ByVal progress As IProgress(Of NumberEntries)) As Task(Of String())
Dim Direc As New DirectoryInfo(dir)
Dim I As Long = 0
' LINQ query for all files
Dim files = From f In Direc.EnumerateFiles("*.*", SearchOption.TopDirectoryOnly)
' Show results
For Each f As FileInfo In files
I += 1
progress.Report(New NumberEntries With {.Count = (I / files.Count), .Eintrag = f.ToString})
Next
End Function
Public Class NumberEntries
Public Count As Long
Public Eintrag As String
End Class
Public Sub ShowProgress(source As Object, e As Object)
Me.ProgressBar1.Value = e.Count * 100
Me.ListBox1.Items.Add(e.eintrag)
End Sub
End Class

