Анимация PictureBox зависает при выполнении задачи - PullRequest
0 голосов
/ 28 июня 2018

Приложение My Winforms показывает анимированный GIF-файл внутри Picturebox во время выполнения длительных операций. Тем не менее, он зависает в ожидании завершения задачи:

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 работала?

EDIT

Это более полное описание моей проблемы, и на этот раз я использовал 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 голосов
/ 28 июня 2018

Вы блокируете поток пользовательского интерфейса, вызывая 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 у вас есть трудоемкая задача, но пользовательский интерфейс не будет заблокирован во время ее выполнения.

...