Laden...

Wo/Wie EventHandler registrieren, wenn die Methode, die das Event auslöst, in extra Thread läuft

Erstellt von MMatze vor 12 Jahren Letzter Beitrag vor 12 Jahren 933 Views
Thema geschlossen
M
MMatze Themenstarter:in
9 Beiträge seit 2011
vor 12 Jahren
Wo/Wie EventHandler registrieren, wenn die Methode, die das Event auslöst, in extra Thread läuft

Hallo

Dank der recht guten Links die ich hier beim letzten Thema von einem Mod bekam, habe ich den Datenaustausch zwischen Forms bzw. Klassen gut hinbekommen. Allerdings habe ich jetzt ein neues Problem und bräuchte wohl einen kleinen Tip.

Ich habe eine Klasse, in deren Methode ein UDP-Server läuft. Weil der blockiert, läuft der in nem Thread. Die Methode bekommt beim starten den port übergeben, z.b Server.udpstart(Port),
daher nutze ich ParameterizedThreadStart.
Das sieht dann so aus:

Thread t = new Thread(new ParameterizedThreadStart(server_udp.startserver));
    t.Start(Convert.ToInt32(tb_serverport.Text));

Ich weiss jetzt nicht, wie ich den Eventhandler registrieren soll.
Normalerweise nimmt man ja einfach das Klassenobjekt.
Ohne Thread:

server_udp t = new server_udp();
t.MyEvent += t_MyEvent;

Kann mir da jemand einen Tip geben?

Das Event soll angestossen werden, wenn der UDP Server Daten empfängt.
Form1 holt sich dann per get die Daten und schreibt sie in die Textbox. Ich hoffe vom Design er ist das so weit OK.

T
2.224 Beiträge seit 2008
vor 12 Jahren

Was spricht dagegen einfach das Objekt zu erstellen und fertig zu initalisieren bevor du den Server startest?
Du kannst dann das fertige Objekte als Parameter übergeben.
Somit ist dein Server Objekt fertig initalisiet.

Ich habe vor einigen Wochen meinen ersten TCP/IP Server mit C# aufgesetzt.
Dafür habe ich die Server- und die Client Komponenten in 2 Klassen(Client und Server) definiert.
Diese bekamen im Konstruktor dann die entsprechenden Parameter wie IP und Port.
Dann muss nur eine Start Methode aufgerufen werden, was man innerhalb eines Threads machen kann, und schon läuft der fertige Server in einem eigenen Thread.

Ähnliches mache ich auch immer wenn ich den ThreadPool verwende.
Erst generiere ich ein Objekt einer Worker Klasse, die sich intern um die eigentliche Verarbeitung und auch um die Signalisierung kümmert.
Und dann wird das fertige Objekt an den Pool übergeben.

Sollte doch auch bei deinem Code machbar sein oder?

Nachtrag:
Du solltest ggf. deine Eingabe beim Port überprüfen lassen.
Ein einfaches Convert.ToIn32 knallt wenn nichts oder kein gültiger Int32 Wert eingegeben wird.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

1.665 Beiträge seit 2006
vor 12 Jahren

Hallo,

so ganz verstehe ich dein Problem jetzt nicht. Wenn du eine Klasse hast, die sich um das UDP Handling kümmert, ist es dir egal, ob die Start-Methode synchron oder asynchron ausgeführt wird.

class UDP
{
    public void Start(int port)
    {
        ThreadPool.QueueUserWorkItem(StartInternal, port);
    }

    private void StartInternal(object _port)
    {
        int port = (int)_port;
        // ...

        if (DeinEvent != null)
        {
            DeinEvent(this, EventArgs.Empty);
        }
    }

    public event EventHandler DeinEvent;
}

von außen aufgerufen:

UDP udp = new UDP();
udp.DeinEvent += DeinEventHandler;
udp.Start(5000);

void DeinEventHandler(object sender, EventArgs e) { }

Der Code ist mehr exemplarisch, sollte dir so jedoch veranschaulichend weiterhelfen.

M
MMatze Themenstarter:in
9 Beiträge seit 2011
vor 12 Jahren

Hi

Danke ersteinmal.
ThreadPool kenne ich nicht, werde mich dann mal damit auseinander setzen.

Ich hab's jetzt so wie JunkyXL beschrieb realisiert und bekomme folgende Fehlermeldung:> Fehlermeldung:

Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement rtb_server erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.

public void DeinEventHandler(object sender, EventArgs e)
        {
            MessageBox.Show(Convert.ToString("pew pew"), "Windows"); 
            this.rtb_server.Text = "test"; //hier InvaldOperationException
        }

Ich schätze, wenn ich mich in ThreadPool eingearbeitet habe, kann ich das Problem selbst lösen 😉

4.942 Beiträge seit 2008
vor 12 Jahren

Hallo MMatze,

mit dem Threadpool hat dieser Fehler nichts zu tun (d.h. auch dort würde er auftauchen), sondern s. Top-FAQ-Beitrag [FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke)

1.665 Beiträge seit 2006
vor 12 Jahren

Die FAQ bringt einfach nichts, wenn sie sich niemand durchliest. Da kann man noch so oft den Link posten:
[FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke)
[FAQ] Warum blockiert mein GUI?

Kurz und primitiv zusammengefasst: Wenn du mit Threads arbeitest und aus einem Thread heraus an deiner grafischen Oberfläche etwas anzeigen willst, musst du mit Invoke arbeiten, da sich das GUI in einem anderen Thread befindet.

M
MMatze Themenstarter:in
9 Beiträge seit 2011
vor 12 Jahren

Ok, das sollte ich wirklich mal machen, danke 😉

Thema geschlossen