Laden...
S
Sourcerer myCSharp.de - Member
Embedded Softwareentwickler Bayern Dabei seit 25.07.2013 9 Beiträge
Benutzerbeschreibung

Forenbeiträge von Sourcerer Ingesamt 9 Beiträge

31.10.2013 - 21:45 Uhr

Hallo herbivore,

ich habe das Attribut ja grade nicht explizit verwendet.
Nach dem Hinweis von Th69 generiert der Compiler für ein Event, dass ohne explizite Accessor Implementierungen deklariert ist, also:


public event Handler Event;

automatisch für die Accessoren das MethodImplOptions.Synchronized Attribut, was von meinem Testcode weiter oben (der das Attribut auch nicht enthält) bestätigt wird.

Dadurch, dass das Attribut hier implizit mit enthalten ist und in den normalen Dokus das nicht erwähnt wird (siehe z.B. Programmierhandbuch Events nach Framework Richtlinien), dachte ich, dass das in der GUI FAQ erwähnt werden sollte.

Sourcerer

31.10.2013 - 15:52 Uhr

Hallo Th69,

danke für den Hinweis.

Daher solltest du nicht die Klasseninstanz per lock (bzw. Monitor.Enter) sperren, sondern möglichst immer ein eigenes Lock-Objekt dafür verwenden.

Habe in meiner Instanz ein Object eingeführt über das ich meine Threads synchronisiere. Funktioniert wunderbar.

@herbivore:
Wäre das nicht ein Punkt für [FAQ] Warum blockiert mein GUI? ?

Vielen Dank für die Hilfe.

Sourcerer

31.10.2013 - 14:18 Uhr

Hallo herbivore,

ich habe nochmal einen Versuch dazu gemacht, und es sieht so aus, als ob die Event Handler Registrierung in .net tatsächlich einen Monitor.Enter o.ä. auf das Objekt, welches das Event beinhaltet, aufruft.
Hier mal der Versuchs Code:


   public partial class Form1 : Form
   {
      Worker worker;
      public Form1()
      {
         InitializeComponent();
         this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);

         worker = new Worker();
         worker.ClientCreated += new Action<Client>(worker_ClientCreated);
         worker.Start();
      }

      void Form1_FormClosing(object sender, FormClosingEventArgs e)
      {
         worker.Stop();
      }

      void worker_ClientCreated(Client obj)
      {
         if (this.InvokeRequired)
         {
            this.Invoke(new Action<Client>(this.worker_ClientCreated), new object[] { obj });
         }
         else
         {
            obj.MyEvent += new Action(obj_MyEvent); // hier ruft .net ein Monitor.Enter o.ä. auf
         }
      }

      void obj_MyEvent()
      {
         
      }
   }

   class Worker
   {
      public event Action<Client> ClientCreated;
      System.Threading.Thread t;

      public Worker()
      {
         t = new System.Threading.Thread(new System.Threading.ThreadStart(this.Runtime));
      }

      public void Start()
      {
         t.Start();
      }

      public void Stop()
      {
         t.Abort();
      }

      void Runtime()
      {
         try
         {
            Client c = new Client();

            System.Threading.Monitor.Enter(c); // Diese Zeile auskommentieren zum Vergleich

            if (this.ClientCreated != null)
            {
               this.ClientCreated(c);
            }

            while (true)
            {
               System.Threading.Thread.Sleep(100);
            }
         }
         catch (Exception)
         {
            return;
         }
      }
   }

   class Client
   {
      public event Action MyEvent;
   }

Wenn der Monitor.Enter Aufruf drinn ist, blockiert die GUI, lässt man ihn weg, funktioniert alles.

Sourcerer

31.10.2013 - 11:17 Uhr

Hallo,

@xxMUROxx:
ich glaube snsewill möchte im voraus wissen wie lange der Durchlauf dauert.

@snsewill:
eine genaue Vorausberechnung eines Schleifendurchlaufs wird dir hier nicht gelingen, da sich dein Programm die Rechenzeit auf dem Prozessor mit anderen Programmen und dem Betriebssystem teilen muss. Ausserdem kannst du nicht voraussagen, wie und wann das Betriebssystem deinem Programm Rechenzeit zuteilt.

Eine solche Berechnung wird normalerweise nur auf Micorcontrollern gemacht, und da auch nur sinnvoll bei Betrachtung des Assembler Codes, da hier das Programm sozusagen "Alleinherscher" ist und 100% der Rechenzeit hat.

Was willst du mit dieser Berechnung eigentlich erreichen?

Wenn du nur wissen willst wie lange das ungefähr dauert, mach mehrmals einen Test mit der von xxMUROxx vorgeschlagenen Lösung und vergleiche die Zeiten.

Sourcerer

31.10.2013 - 10:31 Uhr

Hallo.

habe das Problem gefunden.
Nach der Erzeugung des Client Objekts wird ein

Monitor.Enter(c)

im weiteren Verlauf auf das Objekt im Worker Thread ausgeführt.
Allem Anschein nach macht das .net beim registrieren eines Events auch. Den Hinweis darauf habe ich im Call Stack gefunden, wo stand, dass der Main Thread in einem "sleep, wait, or join" state ist.

Ich habe auf herbivores Hinweis hin das Event geändert:


class Client
{
   public event ClientReceivedDataEventHandler ClientReceivedData
   {
      add
      {
         clientReceivedData += value;
      }
      remove
      {
         clientReceivedData -= value;
      }
   }

   private ClientReceivedDataEventHandler clientReceivedData;
   
   public event ClientRemovedEventHandler ClientRemoved;
}

mit den entsprechenden Registrierungen:


client.ClientReceivedData += new ClientReceivedDataEventHandler(this.ClientReceivedData);
client.ClientRemoved += new ClientRemovedEventHandler(this.ClientRemoved);

Bei der ersten Variante klappt das trotz dem Monitor; bei der zweiten nicht.

DesignFrage: Sollte ich nun den Monitor Aufruf verschieben, um die Eventregistrierung wie gehabt machen zu können, oder add und remove verwenden um die Events gezielt zu schützen?

Sourcerer

30.10.2013 - 17:43 Uhr

Hallo Commuity,

ich hoffe ihr könnt mir hier weiterhelfen, da ich nicht mehr weis wo ich suchen soll.

Im Konstruktor eines User Controls weise ich einem Event von einem Objekt welches in einem anderen Thread erstellt wurde einen Handler zu. Bei dieser Zuweisung blockiert dann die GUI. (=> beim Debuggen der entsprechenden Zeile rückt das Fenster wieder in den Vordergrund, reagiert aber nicht mehr)

Hier mal etwas Code (auf das wesentliche gekürzt um das Firmeninteresse zu wahren):

Code der im Main Thread läuft:


class MainForm
{
   ...
   worker.NewClientFound += new NewClientEventHandler(this.NewClientFound);
   ...
   
   private void NewClientFound(object sender, NewClientEventArgs e)
   {
      if (this.InvokeRequired)
      {
         this.Invoke(new NewClientEventHandler(this.NewClientFound), new object[] { sender, e });
      }
      else
      {
         this.AddClient(e.NewClient);
      }
   }
   
   ...
   
   private void AddClient(Client client)
   {
      ClientGui gui = new ClientGui(client);
      ...
   }
   
   ...
}


class ClientGui : UserControl
{
   public ClientGui(Client client)
   {
      ...
      // hier entsteht der Fehler
      client.ClientReceivedData += new ClientReceivedDataEventHandler(this.ClientReceivedData);
      ...
   }
}

und der Code im Worker Thread:


class Worker
{
   public Worker()
   {
      ....
      this.runtimeThread = new Thread(new ThreadStart(this.Runtime));
      this.runtimeThread.Start();
      ....
   }
   
   ...
   public event NewClientEventHandler NewClientFound;
   ...
   
   private void Runtime()
   {
      ...
      Client c = new Client();
      ...
      if(this.NewClientFound != null)
      {
         NewClientEventArgs args = new NewClientEventArgs(c);
         this.NewClientFound(this, args);
         GC.KeepAlive(args);
      }
      ...
   }
}

Ausgangspunkt des Ganzen ist der Event call in der Worker-Runtime.
Ich bekomme weder eine Fehlermeldung noch eine Exception noch sonst etwas. Die weiteren Threads arbeiten, nur das GUI blockiert.

Hat jemand eine Idee woran das liegen könnte?

Gruß
Sourcerer

28.08.2013 - 09:12 Uhr

Hallo FZelle,

ist ein guter Hinweis mit den 25 Frames.
Ich werde das mal mit einem DGV aufbauen da sie der gewünschten Ansicht am nächsten kommt. Habe im Designer auch entdeckt, dass die Zellen einen WordWrap haben, was mir die Sache doch erleichtert.

Danke für die Hinweise. Habt mir weitergeholfen.

Gruß Sourcerer

27.08.2013 - 10:28 Uhr

Hallo,

danke für die schnellen Antworten.

herbivore:
Die Ansätze bei den Hex Editoren auf CodeProject sind schon nicht schlecht, nur haben die kein Laufzeitproblem, da sie immer Dateien einlesen.

MrSparkle:
Ich hab auch schon dran gedacht das selber zu zeichnen, aber das wird sehr wahrscheinlich zu langsam.

Nochmal zum Hintergrund:
Zwischen den Geräten besteht ein mehrstufiges Kommunikationsprotokoll. (Transportschicht; Sicherungsschicht (TLS); Applikationsschicht....)
Die Daten werden mit 1 MBit übertragen.
Ich hatte schon mal ein (multithreaded) Testprogramm dafür geschrieben, welches die Kommunikation simuliert und dabei Logausgaben (in einer RichTextBox weil farbig) gemacht wenn ein Nachrichtenblock empfangen / gesendet wurde.
Durch die hohe Übertragungsrate kam der PC bei der Logausgabe nicht mehr nach mit dem Anhängen der neuen Ausgaben an die Alten (hatte nach 10k Zeilen ca. 5 min Zeitdifferenz).

Nun soll die Kommunikation nicht mehr simuliert werden, sondern die reale Kommunikation überwacht werden.

Darum frage ich hier nach einem Control, welches die neuen Daten während des Betriebs schnell an die Alten anhängen kann und mir die Möglichkeit gibt, die Ausgabe so zu formatieren, dass die gesendeten und empfangen Blöcke (jeweils links und rechts) untereinander angezeigt werden (siehe oben).
Ich dachte mittlerweile an ein DataGridView, wäre das geeignet?

Vielen Dank für eure Mühe.

Gruß
Sourcerer

26.08.2013 - 17:00 Uhr

Hallo Community,

erstmal vorab "Hallo an alle" da dies mein erster Post ist.

Zum Thema:

ich arbeite gerade an einem Projekt welches Daten zwischen verschiedenen Schnittstellen hin- und herschaufeln soll.
Dabei möchte ich eine Art Monitor mit integrieren um mitlesen zu können was übertragen wird.

Meine Frage dazu: Welche Controls aus den Windows Forms (kein WPF o.ä.) sind für dafür sinnvoll zu verwenden um auch bei größeren Datenmengen nicht in Performanceprobleme zu kommen?
Da ich hauptsächlich für Embedded programmiere und C# "nur" für TestTools verwende, bin ich mit den Controls nicht so bewandert.

Die Ausgabe sollte nach folgendem Schema aufgebaut sein, um sehen zu können wie die zeitliche Abfolge war:

           A            |            B
                        |
01 02 03 04 05 06 07 08 |
09 0A 0B 0C 0D 0E 0F 00 |
                        | 00 01 02 03 04 05 06 07
                        | 08 09 10 11 12 13 14 15
21 22 23 24 25 26 27 28 |
                        | 35 36 37 38 39 3A 3B 3C
                        | 3D 3E 3F 40 41 42 43 44

Der Business-Code dahinter steht schon fast vollständig, es geht mir hier nur um die effiziente Anzeige und die entsprechende Formatierung nach obigem Schema.
Mit dem fertigen Programm soll dann eine Kommunikation zwischen zwei Geräten ge-debuggt werden.

Vielleicht könnt ihr mir auf die Sprünge helfen.

Gruß, Sourcerer.