So beenden Sie eine ausstehende APM-Operation

Wenn Sie eine ausstehende Operation haben, zB

stream.BeginRead(_buffer, 0, _buffer.Length, _asyncCallbackRead, this);

und Sie schließen den Stream-Provider, zB

serialPort.Close();

Sie verursachen nicht überraschend eine Ausnahme.

Gibt es eine bevorzugte Methode, mit der eine ausstehende APM-Operation abgebrochen werden kann, bevor der Port geschlossen wird?

Colbys Antwort ist nicht die Antwort, auf die ich gehofft habe, aber er schließt zumindest eine fruchtlose Allee in der Untersuchung.

Zum Glück habe ich eine Lösung gefunden.

Für jeden Stream pflege ich verschiedene Statusinformationen in einer KlasseDeviceSession. Diese Klasse hat eine MethodeReadStream Bereitstellung der Implementierung für dasAsyncCallback behandelt eingehende Daten.

Beachten Sie, dass_asyncCallbackRead und jede andere Variable, die mit einem Unterstrich beginnt, ist ein privates Mitglied der Klasse, das im Konstruktor von DeviceSession zugewiesen wurde.

Der Konstruktor ruft auch @ zum ersten Mal au_stream.BeginRead.

void ReadStream(IAsyncResult ar)
{
  if (IsOpen) 
    try
    {
      DevicePacket packet;
      int cbRead = _stream.EndRead(ar);
      _endOfValidData += cbRead;
      while ((packet = GetPacket()) != null)
        CommandStrategy.Process(this, packet);
      _stream.BeginRead(_buffer, _endOfValidData, 
        _buffer.Length - _endOfValidData, 
        _asyncCallbackRead, null);
    }
    catch (Exception ex)
    {
      Trace.TraceError("{0}\r\n{1}", ex.Message, ex.StackTrace);
      _restart(_streamProvider, _deviceId);
    }
}

Hinweis, dass ich mich nicht darum gekümmert habe, @ zu setzar.AsyncState. Da der Rückrufdelegat auf die Methode einer bestimmten Instanz von DeviceSession verweist, sind detaillierte und stark typisierte Kontextinformationen (in den Mitgliedern dieser Instanz von DeviceSession enthalten)automatisc im Visier. Dies ist der Punkt, an dem ein Sitzungsobjekt vorhanden ist.

Back beim Abbrechen eines Listeners, das Schließen des Stream-Providers löst den Rückruf aus, aber der Versuch, EndRead aufzurufen, führt zu einemIOException.

Generell weist eine solche Ausnahme auf einen Fehler hin, der einen Neustart des Listeners erfordert, und man möchte darauf reagieren, indem man den Stream-Provider neu startet und die Sitzung neu erstellt. Dies wird durch das Fehlen einer zuverlässigen, vom Stream-Provider unabhängigen Methode erschwert, mit der festgestellt werden kann, ob der Provider einen Fehler begangen hat oder der Benutzer versucht, die Verbindung neu zu starten (z. B. ein neues Gerät an den Port anzuschließen).

Der Trick ist, mehr Kontext hinzuzufügen IsOpen) zumDeviceSession, um anzugeben, ob die Sitzung geöffnet oder geschlossen ist, und um die endgültige Ausführung von @ reibungslos abzuschließeReadStream.

WennIsOpen isttrue dann einIOException ist ein wiederherstellungsbedürftiger Fehler. WennIsOpen istfalse Der Fehler wurde absichtlich verursacht und es sind keine Maßnahmen erforderlich.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage