vb.net - 任务运行时PictureBox动画冻结
问题描述
我的 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
解决方案
您正在通过调用阻止 UI 线程Task.Wait()
。您需要使用 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不会被阻塞。
推荐阅读
- python-3.x - 如何写答案取决于用户在 python 上提出的问题
- python - Python pandas excel导入NameError
- node.js - 我不希望它返回数据库的 _id
- ruby - 编译器未能生成可执行文件。(RuntimeError) 在 macOS 中安装 unf_ext 时
- python - Python:随机琐事琐事问题/答案,在参数中
- ubuntu - Atom 1.54.0 不会在 Ubuntu 20 上启动
- python - 如何使用 python 读取这种对象?
- python-3.x - 从镶木地板文件读取时,熊猫数据类型发生了变化?
- regex - 如何让我的 Perl 单行只显示文件中的第一个正则表达式匹配?
- c - C fork() 输出与预期不同