Avatar billede kamak Praktikant
02. oktober 2008 - 08:32 Der er 8 kommentarer og
2 løsninger

Cross-thread operation not valid

Jeg har en simpel windows application hvor jeg fra en knap starter en tråd som udfører nogle beregninger. Mens tråden kører kan brugeren udfører forskellige ting på formen. Problemet opstår Når tråden er færdig og den skal skrive i en label at den er færdig. Jeg har prøvet forskellige ting men kan ikke komme udenom denne exception: "Cross-thread operation not valid: Control 'label1' accessed from a hread other than the thread it was created on."

Jeg har bla. prøvet med threads og asynchronous delegates. Hvordan kan jeg løse det?

Jeg bør nævne at tråden ikke skal returnere en værdi, da tråden gemmer resultatet i en fil. Så snart filen er updateret skal den indlæses i en label på formen. Pt er der en update knap som brugeren kan trykke på, og hvis tråden endnu ikke har updateret filen må brugeren prøve at trykke på knappen igen lidt senere, for at få updateret sin form. Men dette skulle gerne ske automatisk.
Avatar billede bennytordrup Nybegynder
02. oktober 2008 - 08:37 #1
Du er nødt til at marshalle kaldet tilbage til GUI thread. Det kan du gøre ved følgende:

delegate void StringDelegate(string someValue);

private void UpdateLabel(string newLabelText)
{
  if (this.InvokeRequired)
    this.Invoke(new StringDelgate(UpdateLabel, new object[] { newLabelText }));
  else
    this.labelToUpdate.Text = newLabelText;
}
Avatar billede bennytordrup Nybegynder
02. oktober 2008 - 08:37 #2
Bemærk... Koden er ikke testet, men skrevet efter hukommelsen.
Avatar billede aaberg Nybegynder
02. oktober 2008 - 08:44 #3
Dette er en fejl som opstår når du prøver at ændre på brugergrænsesnittet fra en anden tråd end den som ejer det. Denne fejl har de fleste vel prøvet at få :-)

Løsningen er at bruge Invoke() metoden, som ligger på alle klasser som nedarver fra Control (Forme, labels, knapper osv.). Invoke metoden skal bruge en delegate som parameter. Det Invoke gør, er at køre metoden som delegaten peger på, i brugergrænsesnittets tråd.

Først opretter du en delegate;

public delegate void InvokeDelegate();

når du skal ændre på teksten i din label, skriver du:

this.Invoke(new InvokeDelegate(delegate()
  {
      this.myLabel.Text = "Whatever2;
  }));
Avatar billede kamak Praktikant
02. oktober 2008 - 09:08 #4
Hvor er det smukt :-) Nu virker det, tusing tak for hjælpen tiol jer begge to.

Et hurtig follow up question: Hvad er forskellen på at bruge  "if (this.InvokeRequired)" eller undlade det. f.eks. virker følgende også:

//FORM
delegate void SetTextDelegate(string _SetText);
public void _CrossThreadSetText(string strNew){
Invoke(new SetTextDelegate(_SetText), new object[] { strNew });
}
private void _SetText(string strNew){
label1.Text = strNew;
}

//TRÅD
form1._CrossThreadSetText("test");
Avatar billede kamak Praktikant
02. oktober 2008 - 09:33 #5
aaberg hvis du også laver et svar deler i pointene :-) !
Avatar billede aaberg Nybegynder
02. oktober 2008 - 09:49 #6
:-)
Avatar billede brian0905 Nybegynder
02. oktober 2008 - 11:36 #7
Hvis det bare er en lille applikation og du synes at det her invoke delegte halløj er lidt overkill kan du bare indsætte dette efter din initialize i din constructor:

MyFormName.CheckForIllegalCrossThread..blabla = false;
Avatar billede kamak Praktikant
02. oktober 2008 - 12:54 #8
ok cool, men hvad er faren ved at sætte MyFormName.CheckForIllegalCrossThread..blabla = false;
Risikerer man at programmet går ned i ekstreme tildælde eller ? Jeg tænker  bare der må være en grund til Cross-thread operation...exception opstår
Avatar billede brian0905 Nybegynder
02. oktober 2008 - 12:59 #9
Jepsen der er mange farer, ustabil UI, hængende program og utilsigtet problemer... Igen er det et lille program og du har styr på hvad der opdaterer UI, kan du bruge den som du vil
Avatar billede lasserasch Juniormester
04. oktober 2008 - 23:00 #10
En kommentar ind fra sidelinjen her...

Du kunne også bare vælge at bruge den komponent, som er udviklet til netop at håndtere multi thread operationer for dig.

BackgroundWorker hedder den.

Når du starter en operation i den startes den asynkront (altså i en anden tråd). Har du brug for at opdatere din UI med info (tekst, status eller andet) fra din asynkrone operation, så kaldes ReportProgress. Alt hvad der udføres i reportprogress sker i den kaldende tråd, og derved har du ikke længere noget problem med multithreads operationer...

Den fungerer smukt, men har på fornemmelsen at mange glemmer den, da den måske ikke virker som den indelysende logiske løsning den i virkeligheden er når man oplever din situation første gang.


MVh.
Lasse
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester