Problém je v tom, že metoda CompactDB se spouští v hlavním vlákně. Nově vytvořené okno se nemůže překreslit, dokud neskončí obsluha události, tudíž se nevykreslí ani Label. Doporučuji si napsat takovouto obecnou funkci, která provede předanou metodu v jiném vlákně a přitom zobrazí okno. Píšu to z hlavy, takže to možná není úplně správně, ale to si už doděláte. Fungovat to bude v .NET 4, pro starší verze by se to muselo mírně upravit.
Public Sub LongOperation(text As String, fn As Action)
'zobrazit okno
Dim sw = New StatusWindow(text)
sw.Show()
'spustit úkol v novém vlákně
Dim sc = System.Threading.SynchronizationContext.Current
Task.Factory.StartNew(
Sub()
Dim _exception As Exception
Try
'spustit předanou funkci
fn()
Catch ex As Exception
'zaznamenat případnou výjimku
_exception = ex
End Try
'schovat okno (je nutné přes synchronizationContext, abychom na něj nesahali z jiného vlákna)
sc.Post(
Sub(s)
'schovat okno
sw.Close()
'pokud byla výjimka, zobrazit messagebox
If _exception IsNot Nothing
MsgBox(_exception.Message)
End If
End Sub, Nothing
)
End Sub
)
End Sub
Použití pak vypadá takhle:
Protected Sub Button1_Click( ...
LongOperation("Komprimuji databázi",
Sub()
CompressDB()
End Sub
)
End Sub
Ideální by bylo to zapouzdřit do nějaké třídy LongRunningTask, metodě LongOperation byste předal objekt dědící z nějaké třídy LongRunningTask, který by měl implementovanou nějakou metodu. Hodit se to bude ve chvíli, kdy budete chtít dávat z funkce fn do okna StatusWindow informace, např. kolik procent je již hotovo, nebo měnit text v titulku. Třída LongRunningTask může mít definovanou např. událost ProgressChanged a okno na ni může nějak reagovat.
|