Snippet

Dlouhotrvající operace bez DoEvents

Přidáno: 19.5.2009       Kategorie: Aplikace       Autor: Ondřej Linhart

Již několikrát zde padl dotaz jak spouštět dlouhotrvající operace ve Windows Forms, aniž by došlo k zamrznutí uživatelského rozhraní (amatérské řešení je pomocí DoEvents).

Existuje několik řešení, pro začátečníka je asi nejjednodušší použít komponentu BackgroundWorker, která zajistí vše potřebné pomocí DoWork a RunWorkerCompleted.

Řešení, které vám zde ukážu má oproti BackgroundWorkeru jednu obrovskou výhodu: Můžete spouštět libovolné množství dlouhotrvajících operací současně, tedy na vícejádrovém procesoru může být zpracováváno skutečně několik úloh paralelně (BackgroundWorker dokáže pouze jednu).

Pro rozběhnutí této ukázky postačí vytvořit nový projekt typu Windows Forms Application a na výchozí formulář přidat ListBox. Aby bylo vidět dlouhotrvající zpracování úloh, klikejte libovolně na formulář a sledujte zobrazování dokončených úloh.

Imports System.Threading
Public Class Form1
  Private Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
    'Přidá dlouhotrvající operaci (ComputeNumber) do fronty úloh ke zpracování (ThreadPool)
    'Z důvodu synchronizace (volání ovládacích prvků ze správného vlákna) je nutné
    'předat WindowsFormsSynchronizationContext.Current.
    ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf ComputeNumber), WindowsFormsSynchronizationContext.Current)
  End Sub
  Private Sub ComputeNumber(ByVal uiContext As Object)
    'Vygenerování náhodné hodnoty představující 1-3 vteřiny
    Dim randomizer As New Random
    Dim x = randomizer.Next(1000, 3000)
    'Uspí vlákno na 1-3 vteřiny (simulace náročné činnosti)
    Thread.Sleep(x)
    'Odeslání výsledku ke zobrazení v uživatelském rozhraní
    '(pro naše účely použijeme náhodně vygenerované číslo, jinak by se jednalo
    'o skutečný výsledek dlouhotrvající operace).
    DirectCast(uiContext,  _
               SynchronizationContext).Post(AddressOf AddNumber, x)
  End Sub
  Private Sub AddNumber(ByVal result As Object)
    'V této metodě zobrazíme výsledek dlouhotrvající operace.
    ListBox1.Items.Add(String.Format("Dokončeno za {0:N0} ms", DirectCast(result, Integer)))
  End Sub
End Class 
 

VBNET.CZ | © 2007 Tomáš Herceg, Tomáš Jecha | Kopírování a přejímání jakéhokoliv obsahu z tohoto webu je bez písemného svolení autorů zakázáno.