En GUI som støtter .NETs BackgroundWorker for fremdrift og kansellering av oppgaver

Hver gang jeg snakker om multithreading og asynkron og parallell programmering, spør noen om oppgav kansellering; spesifikt, Windows danner applikasjoner som støtter en Avbryt-knapp og en fremdriftslinje og utfører det faktiske arbeidet atskilt fra UI-tråden slik at applikasjonen ikke ser ut til å henge. Jeg kan forstå hvorfor dette spørsmålet kommer mye opp.

Mens .NET inneholder en innebygd komponent (klassen BackgroundWorker) for å utføre dette arbeidet, er dokumentasjonen ikke veldig tydelig. Jeg har hatt "gleden" av å implementere dette mønsteret, og det er sammensatt nok til at jeg finner meg selv i å kopiere / lime inn fra andre prosjekter for å spare meg selv for innsatsen.

Jeg vil lede deg gjennom prosessen med å lage en enkel skjemaapplikasjon med denne funksjonaliteten. Du er mer enn velkommen til å hoppe foran og ta tak i kildekoden, som er distribuert under MIT-lisensen.

La oss starte med å lage en grunnleggende skjema-applikasjon. Legg til skjemaet to knapper (runButton og CancelButton), en fremdriftslinje (progressBar), en etikett (resultLabel) og et BackgroundWorker-objekt (backgroundWorker). Gi knappene vennlige navn, og fjern tekstegenskapen til resultLabel. Se også på egenskapene til bakgrunnsarbeider i designeren, og sett "WorkerReportsProgress" og "WorkerSupportsCancellation" til True. Skjemaet ditt skal se slik ut:

Nå skal vi lage noen helt grunnleggende logikker for å få applikasjonen i gang. Husk at den asynkrone behandlingen som ble utført av BackgroundWorker, ikke har noen måte å få parametere inn eller ut på. For å kompensere for denne svakheten, oppretter vi en arbeiderklasse (eller prosessor) -klasse som vil ha offentlige egenskaper som representerer inngangsverdiene for arbeidet og resultatet for arbeidet. Denne arbeiderklassen blir oppstartet som en privat variabel i skjemaapplikasjonen (kalt "_processor"), slik at inngangen kan stilles inn av anropsrutinen, og resultatene kan trekkes ut med postkjøringskoden. Slik ser en enkel arbeiderklasse ut:

 bruker System; 

bruker System.ComponentModel;

bruker System.Security.Cryptography;

bruker System.Threading;
 namespace AsynchronousProcessingDemo 

{

klasse prosessor

{

offentlig int Resultater {få; private sett; }

public void PerformWorkAsync (BackgroundWorker worker, DoWorkEventArgs workerArgs)

{

worker.ReportProgress (0);
 /// TODO: fyll ut ditt eget arbeid, avbestillingslogikk og prosjekteringsberegninger 
 for (int teller = 0; teller <= 100; teller ++) 
 { 
 if (arbeider.Annullering i påvente) 
 { 
 // Avbestilling forespurt, avslutt rent 
 worker.ReportProgress (100); 
 workerArgs.Cancel = true; 
 gå i stykker; 
 } 
 Thread.Sleep (250); 

worker.ReportProgress (teller);

}
 var randomNumber = ny byte 1; 
 var rng = new RNGCryptoServiceProvider (); 
 rng.GetBytes (randomNumber); 
 Resultater = Konverter.ToInt32 (randomNumber 0); 
 } 
 } 
 } 

Dette er en veldig grunnleggende klasse. Hvis du trenger inngangsparametere for arbeidet, oppretter du offentlige egenskaper for hver parameter og les dem etter behov i PerformWorkAsync-metoden. (Legg merke til at jeg også stusser produksjonen i en offentlig eiendom; du vil se hvorfor når vi kommer tilbake til hovedformen.)

Det neste vi trenger å gjøre er å skrive funksjonene som omslutter begrepene "å starte arbeid", "kansellere arbeid" og "rydde opp etter arbeid." Vi trenger også en måte å oppdatere fremdriftslinjen på. For dette har vi fire metoder i hovedformklassen:

 privat tomrom Utfør () 

{

runButton.Enabled = falsk;

CancelButton.Enabled = true;

Markør = Markører. Vent Markør;

cancelButton.Cursor = Markører.Default;

backgroundWorker.RunWorkerAsync ();

}
 privat tomrom Avbryt utførelse () 

{

backgroundWorker.CancelAsync ();

CancelButton.Enabled = falsk;

}
 privat tomrom PostExecutionCleanup (bool avbrutt) 

{

CancelButton.Enabled = falsk;

runButton.Enabled = true;

Markør = Markører. Defekt;
 hvis (kansellert) 

{

resultLabel.Text = "Avbrutt";

}

ellers

{

resultLabel.Text = _processor.Resultater.ToString ();

}

}
 privat tomrom UpdateProgressBar (int progress) 

{

progressBar.Value = progress;

}

La oss se nærmere på hva som skjer i hver metode. I Utfør () deaktiverer vi skjemaet (med unntak av avbryt-knappen) mens arbeidet skjer. Så kaller vi RunWorkerAsync () -metoden for backgroundWorker-komponenten. Når RunWorkerAsync () heter, skyter den DoWork-hendelsen, som vi vil håndtere om et øyeblikk. Det er her vi utløser den faktiske prosesseringslogikken. Metoden Avbryt utførelse () signaliserer bakgrunnsarbeider for å utføre en kansellering og deaktiverer avbryt-knappen på skjermen (for å forhindre dobbeltklikking og for å la brukeren vite at noe skjer). PostExecutionCleanup () kalles når arbeidet er fullført, uavhengig av om det var tillatt å kjøre til slutten eller kansellert av brukeren. Metoden UpdateProgressBar () angir bare verdien på fremdriftslinjen på skjermen.

Den siste oppgaven vår er å koble hendelseshåndterere til komponentene på skjemaet og la disse hendelseshåndtererne kalle passende metoder. Alle disse hendelsesbehandlerne er standardhåndteringshåndterere (opprettet ved å dobbeltklikke på komponenten i designeren), bortsett fra ProgressChanged og RunWorkerComplete-hendelser knyttet til backgroundWorker. For å opprette disse hendelsene enkelt, velg komponenten i designeren, klikk hendelsene "lyn" i "Egenskaper" -boksen, skriv inn navnet på metoden du vil bruke for hendelseshåndtereren, og trykk "Enter". Dette vil lage den tomme metoden og knytte den til komponentens hendelse i designerkoden for deg.

 privat tomrom runButton_Click (objekt avsender, EventArgs e) 

{

Henrette();

}
 privat tomrom CancelButton_Click (objekt avsender, EventArgs e) 

{

CancelExecution ();

}
 private void backgroundWorker_DoWork (objekt avsender, DoWorkEventArgs e) 
 { 

_prosessor = ny prosessor ();

_processor.PerformWorkAsync (avsender som BackgroundWorker, e);

}
 privat ugyldig bakgrunnWorker_ProgressChanged (objekt avsender, ProgressChangedEventArgs e) 
 { 
 UpdateProgressBar (e.ProgressPercentage); 
 } 
 privat ugyldig bakgrunnWorker_RunWorkerComplete (objekt avsender, RunWorkerCompletedEventArgs e) 

{

PostExecutionCleanup (e.Cancelled);

}

Nå har du et fullt funksjonelt program som fungerer som et moderne skrivebordsprogram. Denne spesielle applikasjonens funksjonalitet er ikke veldig nyttig; alt det gjør er å kaste bort tid før du produserer et tilfeldig tall. Likevel er det et blunk å ta dette eksempelprosjektet, tilpasse prosessorklassen til å gjøre det du trenger, og endre skjemaet slik at det passer dine behov.

J.Ja

Avsløring av Justin's industri-tilknytning: Justin James har en kontrakt med Spiceworks for å skrive produktkjøpsguider. Han er også under kontrakt med OpenAmplify, som eies av Hapax, for å skrive en serie blogger, opplæringsprogrammer og andre artikler.

-------------------------------------------------- -------------------------------------

Få ukentlige utviklingstips i innboksen Hold utviklerferdighetene dine skarpe ved å registrere deg på TechRepublics gratis nyhetsbrev for Web Developer, levert hver tirsdag. Abonner automatisk i dag!

© Copyright 2021 | pepebotifarra.com