C# szálból kilépés

C# szálból kilépés
2019-09-17T09:18:24+02:00
2019-09-17T16:03:34+02:00
2022-10-15T21:36:41+02:00
aplajoska
Sziasztok!

Foxlearn oldalán találtam egy IoZip-el történő tömörítést. A tömörítés folyamatát progressbaron mutatja. Ez a program jól működik, befejezéskor a formot be lehet zárni. Át szerettem volna módosítani, hogy paraméterezve indítva, csak a tömörítendő fájl nevét és a Zipfájl nevét adom meg. Sikerült is, a program tömörít, de szeretném ha tömörítés után bezárná a formot. Ez nem sikerül. Ebből a szálból nem engedi. Nem vagyok otthon a szálkezelésben, csak azt szeretném elérni, hogy a tömörítés alatt látszódjon a progressbar, ha kész, záruljon be a form. Ide másolom a kódot:

private void TomoritForm_Activated(object sender, EventArgs e) { //Zip file & update process bar thread = new Thread(t => { using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile()) { zip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression; zip.AddFile(Program.sMitFile); zip.SaveProgress += Zip_SaveFileProgress; zip.Save(Program.sZipFile); } }) { IsBackground = true }; thread.Start(); while (bVissza==true) { this.Close(); } } private void Zip_SaveFileProgress(object sender, Ionic.Zip.SaveProgressEventArgs e) { if (e.EventType == Ionic.Zip.ZipProgressEventType.Saving_EntryBytesRead) { progressBar.Invoke(new MethodInvoker(delegate { progressBar.Maximum = 100; progressBar.Value = (int)((e.BytesTransferred * 100) / e.TotalBytesToTransfer); lblSzazalek.Text = progressBar.Value.ToString() + "%"; progressBar.Update(); })); } if (e.EventType==Ionic.Zip.ZipProgressEventType.Saving_Completed) { bVissza = true; } }
Mutasd a teljes hozzászólást!
Két apró megjegyzés. A .NET-ben alapból van ZIP-tömörítő, csak emiatt nem kell külső komponenst használnod. Egyébként meg ne szívasd magad a kézi szálkezeléssel, ha már van async-await.

Egyébként ott nézed be a dolgot, hogy a bVissza értéke kezdetben hamis. A while ciklus megnézi egyszer, hogy true-e az értéke, nem lesz az, és tovább áll.
Helyette csinálhatod azt, hogy ahol a bVissza értékét true-ra állítanád, helyette csinálod ezt:

if (InvokeRequired) Invoke(new Action(this.Close));
Erősen ajánlom, hogy ismerd meg az async-await módszert. Sokkal boldogabb lesz az életed.
Mutasd a teljes hozzászólást!

  • Köszönöm a segítséget, sikerült a form bezárása az általad leírtak szerint. A (InvokeRequired) az mi pontosan? A .NET-ben Zip használatát megnézem, nem hallottam (igaz nem is kerestem) róla.

    Lajos
    Mutasd a teljes hozzászólást!
  • Nagyon röviden az InvokeRequired property azt mondja meg, hogy a pillanatnyilag végrehajtott kódot egy másik szál futtatja-e, mint magát a Form-ot. Az Invoke pedig meghív egy általad megadott metódust a Form szálján, ezzel elkerülve az InvalidOperationException kivételt, ami akkor keletkezik, ha illegális cross-thread hívást csinálsz.

    Valójában helyesen ez a kód így néz ki:

    if (InvokeRequired) Invoke(delegate); else delegate();
    Mutasd a teljes hozzászólást!
  • A szál befejezésére (a te megoldásod előtt) próbáltam theread.Abort() használni, de ez újraindította a tömörítést. Úgy gondoltam az Abort() befejezi a szálat és vissza kerülök a form-ra. Ez miért nem működhetett? A te megoldásod jó. Csak hamarabb bezárja a formot, mint ahogy eléri  a progressbar a 100%-ot optikailag. Valahová késleltetést kellene tenni.

    Lajos
    Mutasd a teljes hozzászólást!
  • Thread-et nem abortálunk, hanem interrupt-olunk. A kettő között az a különbség, hogy amíg az Abort teljesen lelövi a szálat függetlenül az állapotától, azzal jár, hogy nem tud szabályosan leállni. Ezért az Abort deprecated. Az Interrupt pedig egy kivételt vált ki a szálon, ezzel jelezve a szálnak, hogy illő lenne leállnia - vagyis esélyt ad arra, hogy a szál szabályosan leálljon.

    Az, hogy hamarabb bezárja a formot, mint ahogy kijelezné, hogy elkészült, szerintem nem a világvége. Egyébként kikényszeríthetsz a UI-on egy frissítést az Application.DoEvents() metódust meghívva vagy a ProgressBar Invalidate() metódusával.
    Mutasd a teljes hozzászólást!
  • if (e.EventType==Ionic.Zip.ZipProgressEventType.Saving_Completed) { if (InvokeRequired) { Thread.Sleep(50); Invoke(new Action(this.Close)); } } Így már van ideje kiírni a 100%-ot Lajos
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd