30. september 2005 - 18:03Der er
14 kommentarer og 2 løsninger
Threads og progressBar
Hej,
Jeg ved der har været bunker af spm. som dette, men jeg prøver til stadighed at forstå hvordan det fungerer med threads. Har endnu ikke fundet en artikel som forklarer det så jeg kan forstå det :(
Jeg har herunder 2 kode eksempler, og jeg håber så der er en flink ekspert der kan hjælpe mig til at forstå hvad jeg gør forkert.
for (int i = 0; i < noOfSteps; i++) { Thread.Sleep(100); progressBar1.PerformStep(); } }
Ovenstående kode opdaterer min progressBar som den skal, men resulterer i at min GUI "hænger". Derfor skal der noget trådning ind over.
Mit umiddelbare forsøg er så: private void DoWork() { int noOfSteps = 100;
for (int i = 0; i < noOfSteps; i++) { Thread.Sleep(100); progressBar1.PerformStep(); } }
private void button1_Click(object sender, EventArgs e) { t = new Thread(new ThreadStart(DoWork)); t.Start(); }
Det compiles fint, men fejler på runtime, fordi jeg nu foretager "cross-thread operation", og det er så her kæden hopper af for mig. Hvordan skal opdatere min progressBar, hvis jeg ikke må tildele den værdier fra min thread t?
Håber virkelig der er en der kan forklare mig hvordan det hænger sammen, eller alternativt kan pege mig retning af en god pædagoisk artikel/bog om trådning.
Jeg kender godt timer controllen, og det kan godt være jeg skal bruge den, men i så fald er jeg mest ude efter at vide hvorfor jeg skal anvende den i denne sammenhæng?
Du siger at jeg måske skal kalde tråden fra et objekt, ret mig hvis jeg tager fejl, men min button1 er vel også et objekt instantieret ud fra Button-classen?
Som du allerede har fundet ud af er det ikke smart at lave længerevarende arbejde i GUI tråden, idet GUI'et så ikke kan opdatere sig selv. Du kan løse problemet med events, idet du så er sikker på at GUI kaldet udføres i GUI trådens kontekst. Eksempel:
public class Worker { public delegate void ProgressStep(); public event ProgressStep Progress;
Det kan godt se omstændigt ud i sådan et kort eksempel; men i et større system betyder det ikke noget.
Du får også andre fordele, idet du kan have forskellige klasser der arver fra Worker der gør forskellige ting, som alle har muligheden for at sende Progress events ud. Endelig er opdateringen af Progressbar'en løst koblet, så hvis du ønsker at gøre noget andet når der sker fremgang, er du kun nødt til at ændre i din GUI kode.
Det lyder egentlig meget fornuftigt. Jeg måske ca. 20 metoder som kræver trådning, dem er der vel ikke noget i vejen for at placere i samme Worker class?
driis -> Nu har jeg forsøgt at afprøve dit eksempel i praksis, og det giver stadig problemer med "cross-thread operation" når worker_Progress() kaldes..
Selve worker klassen har jeg bare copy-pastet herfra.
Når jeg kører i debug mode i Visual Studio bliver der smidt en exception (InvalidOperationException) på runtime, og editoren hopper til linien: this.progressBar1.PerformStep();
Du får lige den præcise exception beskrivelse: Cross-thread operation not valid: Control 'progressBar1' accessed from a thread other than the thread it was created on.
Det gav pote. Jeg forstår ikke 100% hvad der sker, men det er da et godt udgangspunkt for at jeg kan sætte mig ned og læse lidt om Invoke og Delegates i weekenden.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.