任务运行时图片框动画冻结



我的Winforms应用程序在长时间运行的操作运行时在图片框中显示动画GIF。但是,它在等待任务完成时冻结:

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

为了保持PictureBox的动画运行,我应该采取哪些不同的措施?

编辑

这是对我的问题的更完整的描述,这次我使用了Async/Await(因为我被告知Task.Wait()会阻止调用线程(。现在,动画可以正常移动,直到它第一次到达MyUserControl.BuildFolderMenus(),然后冻结。这是不可避免的吗?我的意思是,动画不是在专用线程中运行的吗?

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

您通过调用Task.Wait()来阻止 UI 线程。您需要使用 Asunc/Await 模式。例如,创建一个这样的方法:

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

然后作为用法:

Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Await MyUserControl1.MyFunction()
End Sub

然后你会看到,虽然你在MyFunction中有一个耗时的任务,但在任务运行时UI不会被阻止。

最新更新