Laden...

UDPClient.BeginReceive -> Thread Context ändern -> Performance-Probleme

Erstellt von CSharperUser vor 13 Jahren Letzter Beitrag vor 13 Jahren 3.840 Views
C
CSharperUser Themenstarter:in
80 Beiträge seit 2010
vor 13 Jahren
UDPClient.BeginReceive -> Thread Context ändern -> Performance-Probleme

Hallo Leute,

ich habe ein kleines Problem und hoffe ihr könnt mir helfen:

In einer eigenen Assembly wird mittels dem UDPClient und der Methode BeginReceive ein asynchrones Lesen eines UDP-Pakets gestartet. Sobald das Paket empfangen wird feuere ich ein Event, für das ich mich in einer anderen Assembly (GUI-Kontext) registriere. Nun muss ich natürlich den Thread wechseln, da ich mich noch in dem Thread der UDP-Assembly befinde und somit nicht auf die UI-Controls zugreifen kann.

Für diesen Wechsel habe ich bereits die Klasse SynchronizationContext bzw. den Dispatcher mit BeginInvoke und Invoke verwendet. Jedoch wird mein Rechner durch diesen Wechsel sehr beansprucht und ich erhalte eine Auslastung von 90%.

Zusätzlich erhalte ich das Receive-Event alle 100 ms, da das Paket alle 10 ms versendet wird und ich im 100 ms-Takt die Daten lese.

Nun meine Frage:
Gibt es eine Möglichkeit den Threadwechsel effizient und performant zu lösen?

Der Code für den UDPClient sieht so aus:



private void RunClient()
{
  if (_udpClient == null)
  {
     _udpClient = new UdpClient((IPEndPoint)_EndPoint) 
                                 {Client = {ReceiveTimeout = 100}};
  }

  var updState = new UdpState {Client = _udpClient, EndPoint = (IPEndPoint)    _EndPoint};
          
   _udpClient.BeginReceive(ReceiveCallback, updState);
}

private void ReceiveCallback(IAsyncResult aAr)
{
   try
  {
      var client = ((UdpState)aAr.AsyncState).Client;
      var endPoint = ((UdpState)aAr.AsyncState).EndPoint;

      var receivedPackage = client.EndReceive(aAr, ref endPoint);

      var socketState = new SocketState(receivedPackage, endPoint, _Port);

      client.BeginReceive(ReceiveCallback, aAr.AsyncState);

      if (DataPackageReceived != null)
     {
         DataPackageReceived(socketState, new NetEventArgs("", "", 0, null));
     }
  }
  catch(Exception exception)
  {
     Trace.WriteLine("Exception on receive action for port: " + exception.Message);
   }
}

Hier die Registrierung in der GUI_Assembly:


...
private NetService _service;
...
private void HandlePackage()
{
  _service.PackageReceived += (sender, e) => SynchronizationContext.Current.Send(delegate { .. });
}

Gelöschter Account
vor 13 Jahren

besser ist es in solch einem Fall nicht zur UI zu pushen sondern von der UI zu pollen.
Dann kannst du das Abholintervall UI-verträglich gestalten und sogar für Low-Performance Hardware adaptiv gestalten.

C
2.121 Beiträge seit 2010
vor 13 Jahren

Ich würd hier ein bisschen mehr Informationen in die Überlegung einbeziehen.
Z.B. die 100 ms. Kommen die Daten alle 100 ms oder nur ab und zu mal und wenn, dann mehrere Pakete in diesem Abstand?
Wenn sie dauernd eintreffen, brauchst du kein Event mehr. Dann ist ja klar dass was kommt. Der Empfänger könnte die Daten in eine Queue schieben und die GUI liest sie aus. Natürlich synchronisiert. Aber die GUI muss dann vielleicht nicht 10 mal pro Sekunde lesen sondern weniger oft und dann dafür mehrere Datensätze.

C
CSharperUser Themenstarter:in
80 Beiträge seit 2010
vor 13 Jahren

Vielen Dank für eure Vorschläge.

Ich habe die Vorschläge nun aufgegriffen und entsprechend in der GUI einen DispatcherTimer alle 100ms laufen. In dem Tick-Event greife ich über die UDP-Schnittstelle auf die aktuellen Daten zu.

Jedoch ergibt sich keine wirkliche Verbesserung der CPU-Auslastung.

Kurz zur weiteren Info:

Der Rechner (Vorgabe durch Firma) hat nur 600 Mhz und Windows XP Embedded. Außerdem wurde die GUI mit WPF erstellt.

Es wird nur ein Paket über UDP versendet. Die Daten werden von einer SPS alle 10 ms versendet mittels Broadcast, d.h. ich bin mit den 100ms schon gut dabei.

Gibt es eventuell noch weitere Ideen? Ich finde einfach keine Optimierung mehr.

U
1.688 Beiträge seit 2007
vor 13 Jahren

Der Rechner (Vorgabe durch Firma) hat nur 600 Mhz und Windows XP Embedded. Außerdem wurde die GUI mit WPF erstellt.

Oh - oh. VIA-CPU mit S3-Grafik? Ich würde mal vermuten, dass Du da mit WPF keine Freude haben wirst.

Was macht denn die Anwendung beim Eintreffen eines UDP-Pakets? Und was passiert (mit der CPU-Last), wenn gar keins kommt?

Gelöschter Account
vor 13 Jahren

hm... WPF ist hier absolut fehl am platz. Ihr seit schon unter den minimalanforderungen des .NET Frameworks.....

Das einzige was dir bleibt, ist das Timerintervall hochzuschrauben.

C
CSharperUser Themenstarter:in
80 Beiträge seit 2010
vor 13 Jahren

Grundlegend ist die Darstellung mittels WPF kein Problem. Solange ich die UDP-Komponente nicht einbinde und dadurch das Netz nicht kontinuierlich abgehört wird, habe ich eine Auslastung von maximal 12%. Die Informationen aus dem UDP-Paket (Größe: ca. 1,4 MB) dienen der Animation von Bewegungen. Sobald ein Paket eintrifft, werte ich die Daten aus und rufe die Animation auf dem Control auf. Dann steigt die CPU-Auslastung auf bis zu 80% und schwankt immer wieder (kommt aber nicht unter 50%).

Bei der Auswertung der Daten starte ich die Animation nur, wenn sich die Daten auch nicht geändert haben.

Ich habe also soweit alles optimiert was geht, aber ich sehe keine Möglichkeit mehr, weniger Auslastung zu erreichen.

Ich habe selbst schon zu einem schnelleren Rechner geraten.

C
CSharperUser Themenstarter:in
80 Beiträge seit 2010
vor 13 Jahren

hm... WPF ist hier absolut fehl am platz. Ihr seit schon unter den minimalanforderungen des .NET Frameworks.....

Das habe ich mir auch schon gedacht. Ich habe jedoch keine direkten Hardware-Anforderungen an WPF bzw. das .NET-Framework gefunden, mit denen ich einen neuen Rechner rechtfertigen könnte. (Wir arbeiten bereits mit dem 4.0-Framework)

@JAck30lena:
Weißt du eventuell einen Link, wo ich die Anforderungen finden kann?
Das mit dem Timer-Intervall hochschrauben hab ich auch schon versucht, hat aber wenig gebracht.

Welche Hardware-Mindestanforderungen würdet ihr mir empfehlen, damit ich für den genannten Fall eine einigermaßen gute Performance erreichen kann?

Gelöschter Account
vor 13 Jahren

Microsoft .NET Framework 4 (eigenständiger Installer) Absatz "Systemanforderungen"

ps: euer Betriebssystem wird da auch nicht unterstützt...

C
CSharperUser Themenstarter:in
80 Beiträge seit 2010
vor 13 Jahren

In Ordnung, vielen Dank. Dann werde ich die Anforderungen mal weitergeben und schauen was passiert.