Autor Beitrag
Soc
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 49



BeitragVerfasst: So 29.11.09 15:21 
Hallo Zusammen,

ich habe einen Windows Dienst erstellt, der wiederum mehrere Worker Threads aufbaut.
Jeder dieser Threads hat eine bestimmte Aufgabe zu erledigen. Er soll durch ein Command "geweckt" werden, diesen dann ausführen, ein Ergebnis zurück liefer und anschliessend wieder schlafen.

Sollte man das über einen Event steuern ? Und wenn ja, wie geht die Kommunikation ?

Gruß

Soc
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: So 29.11.09 18:41 
Solange wir nicht wissen, was für ein Command das sein soll, wo es her kommen soll und wohin das Ergebnis geliefert werden soll, lässt sich leider nicht viel über mögliche Kommunikationswege aussagen.

_________________
>λ=
Soc Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 49



BeitragVerfasst: Mo 30.11.09 10:37 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Solange wir nicht wissen, was für ein Command das sein soll, wo es her kommen soll und wohin das Ergebnis geliefert werden soll, lässt sich leider nicht viel über mögliche Kommunikationswege aussagen.


Hallo Kha,

Der Dienst startet wie gesagt alle Worker Threads.
Diese erledigen Initialisierungsarbeiten und warten dann auf einen Funktionesaufruf.

Als Beispiel dient hier ein Thread, welcher alle Registry Zugriffe übernimmt. Er bekommt z.B. ein Command "Refesh". Damit soll er bestimmte Registry Werte auslesen und neu in eine Liste stellen.
Der Dienst soll dann nach erfolgreicher Arbeit ein "True" oder "false" zurück bekommen.
Bei "false" sollte der Dienst auch eine Fehlermeldung einsehen können, welche er dann dem Message-Thread (dieser kümmert sich um den gesamten Log) zur weiteren Verarbeitung übergibt.

Gruß

Soc
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mo 30.11.09 19:23 
Zumindest bei diesem Beispiel ist ein durchlaufender Nebenthread, der auf Nachrichten wartet, imo fehl am Platze. Starte bei einem "Refresh"-Command doch einfach einen neuen Thread für diese Aufgabe, genau dazu ist der Threadpool da.
Auch denke ich, dass dieser Thread dann gleich sein eigenes Logging übernehmen könnte. Synchronisierung mit anderen Threads scheint mir (bis jetzt) eigentlich nur bei GUI-Anwendungen sinnvoll, weil es dort nötig ist.

_________________
>λ=
Soc Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 49



BeitragVerfasst: Di 01.12.09 09:14 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Zumindest bei diesem Beispiel ist ein durchlaufender Nebenthread, der auf Nachrichten wartet, imo fehl am Platze. Starte bei einem "Refresh"-Command doch einfach einen neuen Thread für diese Aufgabe, genau dazu ist der Threadpool da.


Mh, trotzdem bleibt dann die Frage auf, wie ich einen Response vom Thread zurück bekomme.

Gruß

Soc
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 02.12.09 11:50 
Ein Threadwechsel ist eigentlich nur möglich, indem der eine Thread auf den anderen wartet (was er natürlich auch periodisch machen kann). Deshalb meine Frage: Wozu? Wieso alle zusammenhängenden Arbeitsschritte im gleichen Thread ausführen?

_________________
>λ=
Soc Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 49



BeitragVerfasst: Mo 14.12.09 15:44 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Ein Threadwechsel ist eigentlich nur möglich, indem der eine Thread auf den anderen wartet (was er natürlich auch periodisch machen kann). Deshalb meine Frage: Wozu? Wieso alle zusammenhängenden Arbeitsschritte im gleichen Thread ausführen?


Hallo Kha,

nun, sicherlich könnte ich alle Aufgaben in einen Thread durchführen, würde aber den Thread extrem aufbläahen und hilft bei der Übersicht nicht besonders.
Deshalb habe ich mit überlegt einzelnen Funktionen in einzelnen Threads auszulagern.
Und dabei kommt nun die Frage hoch wie ich eine Kommunikation der einzelnen Threads hin bekomme.

Gruß

Soc
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mo 14.12.09 19:30 
user profile iconSoc hat folgendes geschrieben Zum zitierten Posting springen:
nun, sicherlich könnte ich alle Aufgaben in einen Thread durchführen, würde aber den Thread extrem aufbläahen und hilft bei der Übersicht nicht besonders.
Huch? Wenn die Entscheidung, welche Methode in welchem Thread laufen soll, dein Design beeinflusst, hast du imho etwas falsch gemacht :gruebel: . Jeder andere Ansatz kann in puncto Threading jedenfalls nur wesentlich komplizierter werden.

Es gibt sicherlich Probleme, bei denen "Ein Thread pro Schritt" Sinn macht, bin nur nicht überzeugt, dass das bei dir zutrifft ;) . Die Lösung für solche Fälle heißt BlockingCollection<T> - jedenfalls ab .NET 4.0 :mrgreen: . In diesem Paper (das insgesamt nur zu empfehlen ist :D ) findest du auf Seite 52 eine Implementierung einer ähnlichen Klasse:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
class BlockingQueue<T>
{
  private Queue<T> _queue = new Queue<T>();
  private Semaphore _semaphore = new Semaphore(0int.MaxValue);
  
  public void Enqueue(T data)
  {
    if (data == nullthrow new ArgumentNullException("data");
    lock (_queue) _queue.Enqueue(data);
    _semaphore.Release();
  }

  public T Dequeue()
  {
    _semaphore.Wait();
    lock (_queue) return _queue.Dequeue();
  }
}

Die kannst du als Basis für ein Producer/Consumer-Schema benutzen: Ein Thread schiebt per Enqueue Daten an den nächsten, der durch Dequeue am anderen Ende darauf wartet.

_________________
>λ=
Soc Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 49



BeitragVerfasst: Di 15.12.09 13:39 
Hallo Kha,

danke für den super Tip.
Sicherlich ist es nicht optimal solche Aufteilung in Threads aufzunehmen, aber ein Thread mit allen Funktionen würde sehr unübersichtlich werden.

Trotzdem Danke für die Warnung. Ich werde mir Deine "Lösung" mal anschauen und nochmals über mein Design nachdenken (müßen).

Gruß

Soc