myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Basistechnologien und allgemeine .NET-Klassen » Applikation mit Warteschlange [SyncQueue<T>-Klasse]
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Applikation mit Warteschlange [SyncQueue<T>-Klasse]

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
JuriG JuriG ist männlich
myCSharp.de-Mitglied

Dabei seit: 18.04.2008
Beiträge: 33


JuriG ist offline

Applikation mit Warteschlange [SyncQueue<T>-Klasse]

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo!

ich habe eine (vermutlich) sehr einfache Frage,

ich möchte in meiner c# Konsolenanwendung (die als Dienst läuft), eine Art Warteschlange integrieren,

d.h. Wenn ein Arbeitspaket reinkommt, wird er abgearbeitet, kommt noch ein Arbeitspaket währenddessen rein, wird er in die Warteschlange gepackt und erst später abgearbeitet.

Wie kann ich das am Besten erreichen?

Für die Hilfe wäre ich sehr dankbar!
20.05.2008 16:59 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
tscherno tscherno ist männlich
myCSharp.de-Mitglied

avatar-2584.gif


Dabei seit: 29.04.2007
Beiträge: 630
Entwicklungsumgebung: Visual Studio 2010
Herkunft: Nürnberger Land


tscherno ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

sieh dir mal die Klasse  System.Collections.Generic.Queue an.

Gruss
tscherno
20.05.2008 17:06 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.464
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo tscherno,

wobei die Queue<>-Klasse nicht synchronisiert ist. Und typischerweise werden de Aufträge von unterschiedlichen Threads eingestellt und ausgelesen. Ich habe neulich mal eine minimale, synchronisierte Queue (inkl. kleinem Testprogramm) geschrieben:

C#-Code:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;

//*****************************************************************************
public class SyncQueue <T>
{
   //--------------------------------------------------------------------------
   private Queue <T> _q   = new Queue <T> ();

   //==========================================================================
   // <summary>Trägt einen Eintrag (ohne zu warten) ein</summary>
   public void Enqueue (T tItem)
   {
      lock (this) {
         _q.Enqueue (tItem);
         Monitor.Pulse (this);
         Debug.WriteLine (Thread.CurrentThread.Name + " Enqueue ==> " + _q.Count);
      }
   }

   //==========================================================================
   // <summary>
   //    Holt einen Eintrag aus der Queue heraus und wartet dabei nötigenfalls
   //    solange bis wieder ein Eintrag vorhanden ist.
   // </summary>
   public T Dequeue ()
   {
      lock (this) {
         while (_q.Count == 0) {
            Debug.WriteLine (Thread.CurrentThread.Name + " Wait");
            Monitor.Wait (this);
         }
         Debug.WriteLine (Thread.CurrentThread.Name + " Dequeue ==> " + (_q.Count - 1));
         return _q.Dequeue ();
      }
   }
}

//*****************************************************************************
static class App
{
   //-------------------------------------------------------------------------
   private static SyncQueue <int> _sq   = new SyncQueue <int> ();
   private static Random          _rand = new Random ();

   //==========================================================================
   public static void Main (string [] astrArg)
   {
      Debug.Listeners.Clear ();
      Debug.Listeners.Add (new ConsoleTraceListener ());

      for (int i = 0; i < 4; ++i) {
         Thread t = new Thread (RunDequeue);
         t.Name = "D" + i;
         t.Start ();
      }

      for (int i = 0; i < 4; ++i) {
         Thread t = new Thread (RunEnqueue);
         t.Name = "E" + i;
         t.Start ();
      }

   }

   //==========================================================================
   private static void RunEnqueue ()
   {
      for (int i = 1 ; i <= 25; ++i) {
         _sq.Enqueue (100);
         Thread.Sleep (_rand.Next (1000));
      }
   }

   //==========================================================================
   private static void RunDequeue ()
   {
      for (int i = 1 ; i <= 25; ++i) {
         _sq.Dequeue ();
         Thread.Sleep (_rand.Next (995));
      }
   }
}

herbivore

PS: Der Code ist jetzt auch unter  SyncQueue <T> - Eine praktische Job-Queue verfügbar. Dort findet sich auch eine weitergehende Beschreibung der Klasse.

Suchhilfe: 1000 Worte
21.05.2008 09:00 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
kleines_eichhoernchen kleines_eichhoernchen ist männlich
myCSharp.de-Mitglied

avatar-2079.jpg


Dabei seit: 07.11.2006
Beiträge: 3.971
Entwicklungsumgebung: Visual Studio 2005 (C#)
Herkunft: Ursprünglich Vogtland, jetzt Much


kleines_eichhoernchen ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Herbivore,
gibt es einen speziellen Grund, warum du einmal lock(this) verwendest und einmal Monitor.Enter(this).

Die Queue hat allerdings noch einen weiteren großen Nachteil, Sicherheitskontext ( MSND: SecurityContext Class). Wenn beispielsweise ein Plugin einen Request hinzufügt, das Plugin aber selber nur einen geringen Sicherheitskontext hat, wird es mit dem der Warteschlange ausgeführt (bzw. mit dem Thread, der die Sachen herausholt und verarbeitet). Richtig wäre es den Sicherheitskontext beim hinzufügen festzuhalten und beim Ausführen des Requests dem Thread diesen Sicherheitskontext zu verpassen.
21.05.2008 09:45 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.464
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo kleines_eichhoernchen,

Zitat:
gibt es einen speziellen Grund, warum du einmal lock(this) verwendest und einmal Monitor.Enter(this).

nein, deshalb verwende ich jetzt auch an beiden Stellen lock(this). Danke für den Hinweis.

Was den Sicherheitskontext angeht, kann das in dem von dir beschriebenen Fall natürlich eine Rolle spielen. Es gibt aber sicher mehr Fälle, in denen man das nicht berücksichtigen muss. Du kannst gerne eine Erweiterung schreiben, die den Sicherheitskontext berücksichtigt.

herbivore
21.05.2008 10:04 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegt mehr als ein Jahr.
chavez
myCSharp.de-Mitglied

Dabei seit: 27.02.2007
Beiträge: 252
Entwicklungsumgebung: VS 2010
Herkunft: Österreich


chavez ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Aber erhält man nicht bereits mittels  Queue.Synchronized() eine synchronisierte Queue. Wozu also eine selbst basteln?
15.06.2009 21:03 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.464
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo chavez,

grundsätzlich hast du recht. Man sollte das Rad nicht neu erfinden. Jedoch liefert Queue.Synchronized eine untypisierte Collection, wogegen meine Queue generisch und damit typsicher ist. Der entscheidende Unterschied ist aber, dass Queue.Dequeue eine Exception wirft, wenn die Queue leer ist, statt wie meine Queue zu warten, bis ein Element mit Enqueue hinzugefügt wurde. Also genau das, was man für eine Job-Queue braucht.

herbivore
16.06.2009 07:08 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 11 Jahre.
Der letzte Beitrag ist älter als 10 Jahre.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 27.02.2020 21:25