Avatar billede lasserasch Juniormester
04. december 2023 - 13:03 Der er 2 kommentarer og
1 løsning

Tråd programmering

Nå, jeg kommer lige med et sikkert simpelt spørgsmål.

Der er laaang tid siden jeg har lavet winforms programmering og støder derfor ind i sikkert lidt basis fejl.

Mit setup er : (dette eksempel er selvfølgelig dummy kode, men afspejler den logik som fejler)

Jeg har lavet en winforms applikation som anvender nogle services. f.eks. 'service1'.

På service1 har jeg lavet følgende eventHandler :
  public event StatusEventDelegate.EventHandler StatusUpdate;


'form1' har så en Label kaldet 'lb_status'. Denne viser status for hvad min service laver.

'form1' subscriber så til dette event og sørger for at opdatere 'lb_status' med noget info/status beskeder.

Dette virker super godt, så længe det hele kører i en tråd. Men lige så snart man begynder at starte en ny tråd og i den nye tråd kalder en metode på 'service1', så får man en krydstråds exception når servicen invoker en status update.

Så mit spørgsmål er :

Der må næsten findes en nem måde at få status opdateringslogikken til at køre i hoved tråden selvom den bliver invoked fra en anden tråd.

Det er selvfølgelig ikke et problem i en consol app, men nedenstående konsol kode viser meget godt setup'et. Kan det på en nem måde lade sig gøre at få 'Service1_statusupdate' metoden til at skifte til hoved tråden.


Service1 service1 = new Service1();

service1.StatusUpdate += Service1_StatusUpdate;

void Service1_StatusUpdate(object? sender, EventArgs e)
{
    Console.WriteLine($"This update was made from thread : {Thread.CurrentThread.ManagedThreadId}");
// i en winforms ville følgende linie fejle :
    // lb_status.Text = "Hello World";
}


Console.WriteLine($"Current Thread name is  : {Thread.CurrentThread.ManagedThreadId}");
Task.Factory.StartNew(() =>
{
    service1.MyMethod();
});

Console.WriteLine("Completed");
Console.ReadLine();


public class Service1
{
    public event EventHandler StatusUpdate;
    public void MyMethod()
    {
        Thread.Sleep(1000);
        StatusUpdate?.Invoke(this, new EventArgs());

    }
}
Avatar billede arne_v Ekspert
04. december 2023 - 15:00 #1
Det er et kendt GUI problem.

Aldrig:

somelabel.Text = "Noget";

i en bruger startet tråd eller main tråd - det kan kun bruges i event tråden.

Derfor:

if(somelabel.InvokeRequired)
{
    somelabel.Invoke(() => somelabel.Text = "Noget");
}

for at få den udført i event tråden.

PS: indtastet efter hukommelse så utestet, men der er dokumentation på InvokeRequired og Invoke.
Avatar billede arne_v Ekspert
04. december 2023 - 15:27 #2
Der er et eller andet med lambda og delegate.

Men her er et eksempel som virker:


using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

namespace InvokeAgain
{
    public partial class MainForm : Form
    {
        private int val;
        private Label lbl;
        private Label cnt;
        public MainForm()
        {
            InitializeComponent();
            Size = new Size(450, 150);
            lbl = new Label();
            lbl.Location = new Point(50, 50);
            lbl.Size = new Size(150, 50);
            lbl.Text = "Counter: ";
            Controls.Add(lbl);
            cnt = new Label();
            cnt.Location = new Point(250, 50);
            cnt.Size = new Size(150, 50);
            cnt.Text = val.ToString();
            Controls.Add(cnt);
            new Thread(CounterUpdate).Start();
        }
       
        public void CounterUpdate()
        {
            while(true)
            {
                Thread.Sleep(1000);
                val++;
                if(cnt.InvokeRequired)
                {
                    cnt.Invoke(new Action(() => cnt.Text = val.ToString()));
                }
                else
                {
                    cnt.Text = val.ToString();
                }
            }
        }
    }
    public class Program
    {
        [STAThread]
        public static void Main(string[] args)
        {
            Application.Run(new MainForm());
        }
       
    }
}
Avatar billede lasserasch Juniormester
06. januar 2024 - 19:04 #3
Tak arne. Endte med at bruge invoke og det virker som det skal :-)
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