none
Meldung über aktuellen Status der Anwendung RRS feed

  • Frage

  • Hallo,

    zurzeit versuche ich ein System zu entwickeln, welches Meldungen aus verschiedenen Klassen und Methoden annehmen kann und diese dann in einem Label (WPF) ausgibt.

    Leider habe ich dafür noch keine so richtig brauchbare Lösung gefunden.

    Hat hier jemand Tipps oder Anregungen für mich, die mir helfen würden eine Art ReportController zu erstellen?

    Meine ersten Gedanken gingen an static-class und Warteschlangen-Listen. Finde nur dass meine Dinge irgendwie alle unschön gelöst wurden.

    Gruß

    Aaron

    Samstag, 8. Juli 2017 18:55

Antworten

  • Hi Aaron,
    hier mal eine kleine Demo, damit klar wird, was ich meine:

    using System;
    using System.Collections.Concurrent;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ConsoleApp1
    {
      class Program12
      {
        static void Main(string[] args)
        {
          try
          {
            Prog p1 = new Prog() { Name = "Programm 1" };
            p1.Execute();
            Prog p2 = new Prog() { Name = "Programm 2" };
            p2.Execute();
            Prog p3 = new Prog() { Name = "Programm 3" };
            p3.Execute();
            Console.WriteLine("Weiter, Stoppen mit beliebiger Taste");
            Console.ReadKey();
            p3.Stop();
            p2.Stop();
            p1.Stop();
          }
          catch (Exception ex) { Console.WriteLine(ex.ToString()); }
          Console.WriteLine("Fertig, Abschluss mit beliebiger Taste");
          Console.ReadKey();
        }
    
        /// <summary>
        /// Klasse, die das arbeitende Programm simuliert
        /// </summary>
        internal class Prog
        {
          // Programmname
          internal string Name { get; set; } 
    
          // Möglichkeit für Abbruch
          CancellationTokenSource source = new CancellationTokenSource(); 
          CancellationToken token;
    
          // Konstruktor zur Initialisierung des Abbruch-Tokens
          public Prog() { token = source.Token; } 
    
          // Start des Programme als separater Thread
          internal Task Execute() { return (new TaskFactory(token)).StartNew(Start); }
    
          // Beenden (Abbruch) des Programms
          internal void Stop() { source.Cancel(); }
    
          // Arbeit des Programms
          public async void Start()
          {
            int i = 0;
            while (!source.IsCancellationRequested)
            {
              i++;
              await Prot.Write(Name, $"Protokolleintrag {i}");
              Thread.Sleep(Pause.Random);
            }
          }
        }
    
        /// <summary>
        /// Klasse, die die Protokollfunktion realisiert
        /// </summary>
        internal static class Prot
        {
          /// <summary>
          /// Singleton Protokoll-Klasse
          /// </summary>
          private static Protokoll p = new Protokoll();
    
          /// <summary>
          /// Schreiben eines Eintrags in die Collection
          /// </summary>
          /// <param name="region">Bereichsparameter für Protokoll</param>
          /// <param name="msg">zu protokollierende Nachricht</param>
          /// <returns></returns>
          internal static async Task Write(string region, string msg)
          {
            await Task.Run(() =>
            {
              p.Add(new ProtEintrag() { Region = region, Nachricht = msg, Zeit = DateTime.Now });
            });
          }
    
          /// <summary>
          /// Protokollklasse
          /// </summary>
          internal class Protokoll : BlockingCollection<ProtEintrag>
          {
            /// <summary>
            /// Hinzufügen eines zu protokollierenden Eintrages
            /// </summary>
            /// <param name="item">zu protokollierender Eintrag</param>
            internal protected new void Add(ProtEintrag item)
            {
              base.Add(item);
              are.Set(); // Anzeige, dass neuer Eintrag vorliegt
            }
    
            // Klassenfelder
            private AutoResetEvent are = new AutoResetEvent(false);
            private CancellationTokenSource source = new CancellationTokenSource();
            private CancellationToken token;
            private Random rnd = new Random(); // Zufallszahl für Simulation des Zeitaufwandes
    
            /// <summary>
            /// Konstruktor, der den Thread für die Ablage der Protokolleinträge startet
            /// </summary>
            public Protokoll()
            {
              token = source.Token;
              (new TaskFactory(token)).StartNew(() =>
              {
                while (true)
                {
                  are.WaitOne();
                  while (this.Count > 0)
                  {
                    var eintrag = this.Take();
                    // Ausgabe
                    Console.WriteLine($"{eintrag.Zeit:HH.mm.ss} {eintrag.Region} {eintrag.Nachricht}");
                    // Zeitaufwand für Protokollablage simulieren
                    Thread.Sleep(rnd.Next(100, 300));
                  }
                }
              });
            }
            /// <summary>
            /// Destructor für das Aufräumen, z.B. Datei schließen
            /// </summary>
            ~Protokoll()
            {
              // aufräumen
              base.Dispose();
            }
          }
        }
    
        /// <summary>
        /// Klasse für einen Protokolleintrag
        /// </summary>
        internal class ProtEintrag
        {
          internal string Region { get; set; }
          internal string Nachricht { get; set; }
          internal DateTime Zeit { get; set; }
        }
    
    
        /// <summary>
        /// Hilfsklasse für eine zufällige Wartungszeit
        /// </summary>
        internal static class Pause
        {
          static Random rnd = new Random();
          public static int Random { get { return rnd.Next(100, 1000); } }
        }
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort vorgeschlagen Peter Fleischer Sonntag, 9. Juli 2017 06:17
    • Als Antwort markiert Triky313 Montag, 10. Juli 2017 07:32
    Sonntag, 9. Juli 2017 05:55

Alle Antworten

  • Hi Aaron,
    Deine Idee geht in die richtige Richtung.

    Baue eine statische Klasse mit einer statischen WriteProtokoll-Methode. In der Methode erzeugst Du aus den übergebenen Parametern ein Nachrichten-Objekt (z.B. mit Nachricht, Quelle, Zeit, Prozess-ID usw.). Dieses Objekt wird einer statische BlockingCollection hinzugefügt. Außerdem wird über ein Signal (z.B. AutoResetEvent) über eine neue Nachricht informiert.

    Mit dem Start der Klasse (statischer Konstruktor) oder dem erstmaligen Aufruf der WriteProtokoll-Methode wird ein Thread für die Ausgabe der Protokolldaten gestartet. In diesem Thread läuft eine Schleife, die auf neue Nachrichte-Objekte wartet und dann alle vorhandenen Nachrichten-Objekte ausgibt und wieder ins Warten geht. Im Destructor kann dann die Schleife beendet und aufgeräumt werden.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks


    Samstag, 8. Juli 2017 19:15
  • Hi Aaron,
    hier mal eine kleine Demo, damit klar wird, was ich meine:

    using System;
    using System.Collections.Concurrent;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ConsoleApp1
    {
      class Program12
      {
        static void Main(string[] args)
        {
          try
          {
            Prog p1 = new Prog() { Name = "Programm 1" };
            p1.Execute();
            Prog p2 = new Prog() { Name = "Programm 2" };
            p2.Execute();
            Prog p3 = new Prog() { Name = "Programm 3" };
            p3.Execute();
            Console.WriteLine("Weiter, Stoppen mit beliebiger Taste");
            Console.ReadKey();
            p3.Stop();
            p2.Stop();
            p1.Stop();
          }
          catch (Exception ex) { Console.WriteLine(ex.ToString()); }
          Console.WriteLine("Fertig, Abschluss mit beliebiger Taste");
          Console.ReadKey();
        }
    
        /// <summary>
        /// Klasse, die das arbeitende Programm simuliert
        /// </summary>
        internal class Prog
        {
          // Programmname
          internal string Name { get; set; } 
    
          // Möglichkeit für Abbruch
          CancellationTokenSource source = new CancellationTokenSource(); 
          CancellationToken token;
    
          // Konstruktor zur Initialisierung des Abbruch-Tokens
          public Prog() { token = source.Token; } 
    
          // Start des Programme als separater Thread
          internal Task Execute() { return (new TaskFactory(token)).StartNew(Start); }
    
          // Beenden (Abbruch) des Programms
          internal void Stop() { source.Cancel(); }
    
          // Arbeit des Programms
          public async void Start()
          {
            int i = 0;
            while (!source.IsCancellationRequested)
            {
              i++;
              await Prot.Write(Name, $"Protokolleintrag {i}");
              Thread.Sleep(Pause.Random);
            }
          }
        }
    
        /// <summary>
        /// Klasse, die die Protokollfunktion realisiert
        /// </summary>
        internal static class Prot
        {
          /// <summary>
          /// Singleton Protokoll-Klasse
          /// </summary>
          private static Protokoll p = new Protokoll();
    
          /// <summary>
          /// Schreiben eines Eintrags in die Collection
          /// </summary>
          /// <param name="region">Bereichsparameter für Protokoll</param>
          /// <param name="msg">zu protokollierende Nachricht</param>
          /// <returns></returns>
          internal static async Task Write(string region, string msg)
          {
            await Task.Run(() =>
            {
              p.Add(new ProtEintrag() { Region = region, Nachricht = msg, Zeit = DateTime.Now });
            });
          }
    
          /// <summary>
          /// Protokollklasse
          /// </summary>
          internal class Protokoll : BlockingCollection<ProtEintrag>
          {
            /// <summary>
            /// Hinzufügen eines zu protokollierenden Eintrages
            /// </summary>
            /// <param name="item">zu protokollierender Eintrag</param>
            internal protected new void Add(ProtEintrag item)
            {
              base.Add(item);
              are.Set(); // Anzeige, dass neuer Eintrag vorliegt
            }
    
            // Klassenfelder
            private AutoResetEvent are = new AutoResetEvent(false);
            private CancellationTokenSource source = new CancellationTokenSource();
            private CancellationToken token;
            private Random rnd = new Random(); // Zufallszahl für Simulation des Zeitaufwandes
    
            /// <summary>
            /// Konstruktor, der den Thread für die Ablage der Protokolleinträge startet
            /// </summary>
            public Protokoll()
            {
              token = source.Token;
              (new TaskFactory(token)).StartNew(() =>
              {
                while (true)
                {
                  are.WaitOne();
                  while (this.Count > 0)
                  {
                    var eintrag = this.Take();
                    // Ausgabe
                    Console.WriteLine($"{eintrag.Zeit:HH.mm.ss} {eintrag.Region} {eintrag.Nachricht}");
                    // Zeitaufwand für Protokollablage simulieren
                    Thread.Sleep(rnd.Next(100, 300));
                  }
                }
              });
            }
            /// <summary>
            /// Destructor für das Aufräumen, z.B. Datei schließen
            /// </summary>
            ~Protokoll()
            {
              // aufräumen
              base.Dispose();
            }
          }
        }
    
        /// <summary>
        /// Klasse für einen Protokolleintrag
        /// </summary>
        internal class ProtEintrag
        {
          internal string Region { get; set; }
          internal string Nachricht { get; set; }
          internal DateTime Zeit { get; set; }
        }
    
    
        /// <summary>
        /// Hilfsklasse für eine zufällige Wartungszeit
        /// </summary>
        internal static class Pause
        {
          static Random rnd = new Random();
          public static int Random { get { return rnd.Next(100, 1000); } }
        }
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort vorgeschlagen Peter Fleischer Sonntag, 9. Juli 2017 06:17
    • Als Antwort markiert Triky313 Montag, 10. Juli 2017 07:32
    Sonntag, 9. Juli 2017 05:55