Frage

Mein C # Anwendung ist so, dass ein Hintergrundarbeiter für die Anerkennung einiger übertragenen Daten zu warten, verwendet wird. Hier ist einig Pseudo-Code demonstriert, was ich versuche zu tun:

UI_thread
{
   TransmitData()
   {
      // load data for tx
      // fire off TX background worker
   }

   RxSerialData()
   {
      // if received data is ack, set ack received flag
   }
}

TX_thread
{
   // transmit data
   // set ack wait timeout
   // fire off ACK background worker
   // wait for ACK background worker to complete
   // evaluate status of ACK background worker as completed, failed, etc.
}

ACK_thread
{
   // wait for ack received flag to be set
}

Was passiert, ist, dass der ACK Background mal aus, und die Bestätigung nie erhalten. Ich bin ziemlich sicher, dass es von dem Remote-Gerät übertragen wird, weil das Gerät nicht verändert hat, und die C # .NET-Anwendung sendet. Ich habe den ack Faden von diesem geändert wird (wenn es funktioniert) ...

for( i = 0; (i < waitTimeoutVar) && (!bAckRxd); i++ )
{
   System.Threading.Thread.Sleep(1);
}

... dazu ...

DateTime dtThen = DateTime.Now();
DateTime dtNow;
TimeSpan stTime;

do
{
   dtNow = DateTime.Now();
   stTime = dtNow - dtThen;
}
while ( (stTime.TotalMilliseconds < waitTimeoutVar) && (!bAckRxd) );

Letzteres erzeugt eine sehr acurate Wartezeit, wie die ehemaligen verglichen. Aber ich frage mich, ob die Entfernung der Sleep-Funktion ist mit der Fähigkeit interferring serielle Daten zu empfangen. Does C # erlaubt nur ein Thread zu einem Zeitpunkt ausgeführt werden, das heißt, muß ich irgendwann Fäden in dem Schlaf zu setzen, um andere Threads zu erlauben zu laufen?

Alle Gedanken oder Vorschläge haben würde möglicherweise geschätzt. Ich bin mit Microsoft Visual C # 2008 Express Edition. Danke.

War es hilfreich?

Lösung

Ihre „neue“ Version des RX-Thread nutzt 100% der Prozessorzeit - es läuft nur kontinuierlich und niemals schläft. Neben der allgemeinen bösartige Natur dieses Ansatzes, diese Macht (wenn auch nicht sicher) zu verhindern, einige andere Dinge, wie Daten zu empfangen, von auf Zeit geschieht.

Für Warte Szenarien wie diese, würde man in der Regel ein Thread Synchronisierungskonstrukt verwenden genannt Ereignis . Sie erstellen ein „Ereignis“ Objekt und die RX-Thread wartet auf sich, während des Verarbeitungs-Thread Signale das Ereignis, wenn der ACK empfangen wird.

AutoResetEvent event = new AutoResetEvent( false );

// ...
// ACK waiting thread:
event.WaitOne();
// ...

// ...
// Whatever thread actually receives the ACK
if ( /* ack received */ )
{
    // bAckRxd = true; - comment this out. Replace with following:
    event.Set();
}

Was, warum genau sind Sie Ihre ACK nicht empfangen, ich brauche mehr Informationen. Was genau ist der Kanal? Ist es eine serielle Schnittstelle? Netzwerk? Rohr? Etwas anderes?

Andere Tipps

Um die direkte Frage, ob nicht C # Antwort ein Thread erlaubt zu einer Zeit auszuführen, wird C # nichts mit Threading zu tun hat. Der .NET-Framework wird jedoch können Sie mehr (logisch) Threads zu einem Zeitpunkt ausgeführt werden. Wie das tatsächlich behandelt, ist eine Funktion des Rahmens und das OS.

Wie für Ihr Problem, ich glaube, Sie haben zu viele Threads in einem Wartezustand zu beginnen. Ihre Methoden zum Senden und Empfangen der Daten Asynchron-Call-Modelle auf sie haben sollten (Anfang und Ende). Aus diesem Grund sollten Sie Ihre Übertragung mit einem Aufruf starten zu beginnen und dann einen Rückruf anhängen, die aufgerufen wird, wenn die Funktion beendet.

Dann wird in der Callback, würden Sie das Ergebnis bearbeiten und auf den nächsten async Betrieb gehen (falls erforderlich) oder die Benutzeroberfläche aktualisieren.

Der Code ist eher faden glücklich. Dass in der Tat kann man in Schwierigkeiten geraten, wenn man ihnen Zeit Dinge erwarten. Besonders, wenn man BGW oder Threadpool Threads verwenden, nur der Scheduler ermöglicht es ihnen zu laufen, wenn es nicht mehr Threads aktiv, als Sie CPU-Kerne haben. Oder wenn Fäden erhalten „stecken“ für eine Weile. Mit freundlichen stecken bleiben. Sie nicht auch sie scheinen effektiv zu nutzen, Abfrageschleifen brennen viele unnötige CPU-Zyklen.

Nutzen Sie die Fähigkeiten der Serialport Klasse diese zu vermeiden:

  • Sie brauchen nicht einen Sendegewinde. Der serielle Port-Treiber hat einen Puffer, Ihre Write () Anruf wird sofort zurück, wenn die Daten den Puffer paßt. Das Schreiben vom Haupt-Thread ist in Ordnung.
  • Sie brauchen nicht unbedingt ein Thread erhalten. Serielle Schnittstelle hat bereits ein, es läuft das DataReceived Ereignis. Es kann einen Timer stoßen, dass Sie begonnen haben, wenn Sie die Daten übertragen werden.
  • Serialport hat bereits eine Eigenschaft Readtimeout. Sie können es in einem verwenden Thread zu Timeout der Read () Anruf erhalten.

Sleep () nicht mit seriellen Schnittstellen stören, ihre Fahrer gelesenen Daten Hardware-Interrupts verwendet wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top