Vb.net 任务运行时PictureBox动画冻结

Vb.net 任务运行时PictureBox动画冻结,vb.net,task,Vb.net,Task,当长时间运行操作时,我的Winforms应用程序在picturebox中显示动画gif。但是,它在等待任务完成时冻结: Public Class MyUserControl Sub Initialize() Dim folderscantask = Task.Factory.StartNew( Function() EwsManagedApiScanFolderHierarchy(), TaskCreationOptions

当长时间运行操作时,我的Winforms应用程序在picturebox中显示动画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不会被阻止。

您通过调用
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不会被阻止。

您对
folderdictask.Wait()的调用将阻止当前线程,直到任务完成,因此您并不是在异步运行它。Look into.Async/Await是我的第一种方法,但它会使运行流过早地从方法返回,在扫描文件夹层次结构和向UIT添加相应的菜单项之前。当您有一些操作不太正确时,如果您想在特定行等待任务,则必须使用它。当然,在当前状态下,您也可以切换回旧方法。我认为您应该关注异步/等待方法不起作用的原因,而不是尝试将当前代码修复为异步/等待是执行异步工作的一种非常简单和强大的方法。也许递归是问题的一部分?不要担心下一票-我会说这是关于个人的主题您对
folderdictask.Wait()的调用将阻止当前线程,直到任务完成,所以您并不是在异步运行此线程。Look into.Async/Await是我的第一种方法,但它会使运行流过早地从方法返回,在扫描文件夹层次结构和向UIT添加相应的菜单项之前。当您有一些操作不太正确时,如果您想在特定行等待任务,则必须使用它。当然,在当前状态下,您也可以切换回旧方法。我认为您应该关注异步/等待方法不起作用的原因,而不是尝试将当前代码修复为异步/等待是执行异步工作的一种非常简单和强大的方法。也许递归是问题的一部分?不要担心否决票——我会说这是关于@VBobCat的个人提示:要从异步函数返回某些内容,请将返回类型
任务(属于您的类型)
,在您的例子中:
异步函数EwsManagedApiScanFolderHierarchy()作为任务(属于字典(字符串,字符串))
请注意@VBobCat:要从异步函数返回内容,请将返回类型设置为
任务(属于您的类型)
,在您的示例中:
异步函数EwsManagedApiScanFolderHierarchy()作为任务(属于字典(属于字符串,字符串))