任务运行时PictureBox动画冻结

时间:2018-06-28 15:07:10

标签: vb.net task

我的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

1 个答案:

答案 0 :(得分:4)

您正在通过调用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。