问题
My Winforms application shows an animated gif inside a picturebox while long running operations run. However, it freezes while waiting for the completion of the task:
Public Class MyUserControl
Sub Initialize()
Dim folderscantask = Task.Factory.StartNew(
Function() EwsManagedApiScanFolderHierarchy(),
TaskCreationOptions.LongRunning
)
folderdictask.Wait()
Dim folderscanresult = folderscantask.Result
End Sub
Function EwsManagedApiScanFolderHierarchy() As Dictionary(Of String, String)
'Performs a long, recursive operation involving a
'Microsoft.Exchange.WebServices.Data.ExchangeService object
End Function
End Class
What should I do differently in order to keep PictureBox's animation running?
EDIT
This is a more complete description of my problem, and this time I used Async/Await (since I was taught that Task.Wait() would block the caller thread). Now, animation moves fine until it reaches MyUserControl.BuildFolderMenus() for the first time, then it freezes. Is this inevitable? I mean, don't animations run in a dedicated thread?
Public Class MyForm : Inherits Form
'Form has a PictureBox named PictureBoxWaiting that shows an animated gif
Public Async Sub MyButton_Click(sender as Object, e as EventArgs) Handles MyButton.Click
PictureBoxWaiting.Show()
PictureBoxWaiting.BringToFront()
Await MyUserControl1.Initialize()
PictureBoxWaiting.Hide()
MyUserControl1.Show()
End Sub
End Class
Public Class MyUserControl
Public Async Function Initialize() As Task
Dim folderdic = Await GetFolderHierarchyAsync()
BuildFolderMenus(ToolStripDropDownButtonFolders, folderdic)
End Function
Public Async Function GetFolderHierarchyAsync() As Task(Of Dictionary(Of String, String))
Return Await Task.Factory.StartNew(
Function() EwsManagedApiScanFolderHierarchy(),
TaskCreationOptions.LongRunning
)
End Function
Function EwsManagedApiScanFolderHierarchy() As Dictionary(Of String, String)
'Performs a long, recursive operation involving a
'Microsoft.Exchange.WebServices.Data.ExchangeService object
End Function
Private Sub BuildFolderMenus(menu As ToolStripDropDownItem, dic As Dictionary(Of String, String))
'This reads the dictionary containing the folder hierarchy
'and recursively adds menu items in order that folders´
'subfolders correspond to subitems inside an item
'
'This must run in UI thread since it creates UI controls
End Sub
End Class
回答1:
You are blocking the UI thread by calling Task.Wait(). You need to use Asunc/Await pattern. For example create a method like this:
Public Async Function MyFunction() as Task
Await Task.Run(Sub()
' Do something non-UI which is time-consuming
' This code runs in another thread without blocking UI
' For example Thread.Sleep(5000)
End Sub)
'The code here runs is UI thread
End Function
And then as the usage:
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Await MyUserControl1.MyFunction()
End Sub
Then you will see, although you have a time-consuming task in MyFunction, but the UI will not be blocked while the task is running.
来源:https://stackoverflow.com/questions/51086223/picturebox-animation-freezing-while-task-running