73 Stimmen

In .NET, in welchem Thread werden Ereignisse behandelt?

Ich habe versucht, ein Producer/Consumer-Muster in c# zu implementieren. Ich habe einen Consumer-Thread, der eine gemeinsame Warteschlange überwacht, und einen Producer-Thread, der Elemente in die gemeinsame Warteschlange stellt. Der Producer-Thread ist abonniert, um Daten zu erhalten... das heißt, es hat einen Event-Handler, und nur sitzt herum und wartet auf ein OnData-Ereignis zu feuern (die Daten werden von einer dritten Partei api gesendet). Wenn er die Daten erhält, stellt er sie in die Warteschlange, damit der Verbraucher sie verarbeiten kann.

Wenn das OnData-Ereignis im Producer ausgelöst wird, hatte ich erwartet, dass es von meinem Producer-Thread behandelt wird. Aber das scheint nicht der Fall zu sein. Das OnData-Ereignis scheint, als ob es stattdessen auf einem neuen Thread behandelt wird! Ist dies, wie .net immer funktioniert ... Ereignisse sind auf ihren eigenen Thread behandelt? Kann ich steuern, welcher Thread die Ereignisse behandelt, wenn sie ausgelöst werden? Was ist, wenn Hunderte von Ereignissen fast gleichzeitig ausgelöst werden... würde jedes seinen eigenen Thread haben?

111voto

Dean Harding Punkte 69243

Nachdem ich die Frage noch einmal gelesen habe, glaube ich, dass ich das Problem jetzt verstehe. Sie haben im Grunde etwas wie dieses:

class Producer
{
    public Producer(ExternalSource src)
    {
        src.OnData += externalSource_OnData;
    }

    private void externalSource_OnData(object sender, ExternalSourceDataEventArgs e)
    {
        // put e.Data onto the queue
    }
}

Und dann gibt es einen Verbraucher-Thread, der Dinge aus dieser Warteschlange abruft. Das Problem ist, dass das OnData-Ereignis von Ihrem ExternalSource Objekts - egal auf welchem Thread es gerade läuft.

C# event s sind im Grunde nur eine einfach zu bedienende Sammlung von Delegaten und "Feuern" ein Ereignis nur bewirkt, dass die Laufzeit durch alle der Delegaten Schleife und feuern sie ein zu einer Zeit.

Ihr OnData-Ereignishandler wird also in dem Thread aufgerufen, in dem die ExternalSource läuft.

29voto

Adam Robinson Punkte 176996

Es gibt nichts Besonderes an der Art und Weise, wie Ereignisse aufgerufen werden, und Ihr Producer-Thread hat keinen Event-Handler, Ihr Producer-Thread hat einfach gesagt "Hey, wenn du dieses Ereignis auslöst, rufe diese Funktion auf". Es gibt nichts, was bewirkt, dass die Ereignisausführung auf dem anhängenden Thread oder auf seinem eigenen Thread stattfindet (es sei denn, Sie würden BeginInvoke anstatt den Delegaten des Ereignisses normal aufzurufen, aber dadurch wird er nur auf der ThreadPool ).

18voto

Konstantin Spirin Punkte 19144

Auslösen eines Ereignisses mit Invoke ist dasselbe wie der Aufruf einer Methode - sie wird in demselben Thread ausgeführt, in dem Sie sie ausgelöst haben.

Auslösen eines Ereignisses mit BeginInvoke verwendet ThreadPool . Hier sind einige kleinere Details

-5voto

venky Punkte 1

Sie müssen autoresetevent Handler für dieses Problem.....in autoresetevent verwenden, wenn Produzent produses es das Signal dann Verbraucher zurückgesetzt sein Signal und verbrauchen. nach verbrauchen verbrauchen gesetzt Signal dann nur Produzent produziert...

AutoResetEvent pro = new AutoResetEvent(false);
AutoResetEvent con = new AutoResetEvent(true);

public void produser()
{

    while(true)
    {
        con.WaitOne();

        pro.Set();
    }
}

public void consumer()
{
    while (true)
    {
    pro.WaitOne();
       .................****

    con.Set();
    }
}

private void button1_Click(object sender, EventArgs e)
{
    Thread th1 = new Thread(produser);
    th1.Start();
    Thread th2 = new Thread(consumer);
    th2.Start();
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X