it-swarm.com.de

Richtig abfragen?

Ich bin ein Software-/Hardware-Ingenieur mit einiger Erfahrung in C- und Embedded-Technologien. Derzeit bin ich damit beschäftigt, einige Anwendungen in C # (.NET) zu schreiben, die Hardware zur Datenerfassung verwenden. Nun die folgende für mich brennende Frage:

Zum Beispiel: Ich habe eine Maschine, die über einen Endschalter verfügt, um die Endposition einer Achse zu ermitteln. Jetzt verwende ich ein USB-Datenerfassungsmodul zum Lesen der Daten. Derzeit verwende ich einen Thread, um kontinuierlich den Portstatus zu lesen.

Auf diesem Gerät gibt es keine Interrupt-Funktion.

Meine Frage: Ist das der richtige Weg? Soll ich Timer, Threads oder Aufgaben verwenden? Ich weiß, dass Umfragen etwas sind, das die meisten von euch "hassen", aber jeder Vorschlag ist willkommen!

17
Velocity

IMO, das hängt stark von Ihrer genauen Umgebung ab, aber zunächst einmal - Sie sollten Threads in den meisten Fällen nicht mehr verwenden. Tasks sind dafür die bequemere und leistungsfähigere Lösung.

  • Niedrige Abrufhäufigkeit: Timer + Abfrage im Ereignis Tick:
    Ein Timer ist einfach zu handhaben und zu stoppen. Sie müssen sich keine Gedanken darüber machen, dass Threads/Aufgaben im Hintergrund ausgeführt werden. Die Handhabung erfolgt jedoch im Haupt-Thread

  • Mittlere Abrufhäufigkeit: Task + await Task.Delay(delay):
    await Task.Delay(delay) blockiert keinen Thread-Pool-Thread, aber aufgrund des Kontextwechsels beträgt die minimale Verzögerung ~ 15ms

  • Hohe Abrufhäufigkeit: Task + Thread.Sleep(delay)
    verwendbar bei Verzögerungen von 1 ms - dies geschieht tatsächlich, um unser USB-Messgerät abzufragen

Dies könnte wie folgt implementiert werden:

int delay = 1;
var cancellationTokenSource = new CancellationTokenSource();
var token = cancellationTokenSource.Token;
var listener = Task.Factory.StartNew(() =>
{
    while (true)
    {
        // poll hardware

        Thread.Sleep(delay);
        if (token.IsCancellationRequested)
            break;
    }

    // cleanup, e.g. close connection
}, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);

In den meisten Fällen können Sie einfach Task.Run(() => DoWork(), token) verwenden, aber es gibt keine Überladung, um die Option TaskCreationOptions.LongRunning bereitzustellen, die den Taskplaner anweist, keinen normalen Thread-Pool-Thread zu verwenden.
Wie Sie sehen, sind Tasks einfacher zu handhaben (und awaitable, trifft hier aber nicht zu). Insbesondere das "Stoppen" ruft in dieser Implementierung cancellationTokenSource.Cancel() von überall im Code auf. 

Sie können dieses Token sogar in mehreren Aktionen freigeben und gleichzeitig stoppen. Noch nicht gestartete Aufgaben werden auch nicht gestartet, wenn das Token abgebrochen wird.

Sie können auch eine andere Aktion an eine Aufgabe anhängen, um sie nach einer Aufgabe auszuführen:

listener.ContinueWith(t => ShutDown(t));

Dies wird dann ausgeführt, nachdem der Listener abgeschlossen wurde und Sie können eine Bereinigung durchführen (t.Exception enthält die Ausnahme der Task-Aktion, falls diese nicht erfolgreich war).

36
ChrFin

IMO-Abfrage kann nicht vermieden werden.

Sie können ein Modul mit einem unabhängigen Thread/Task erstellen, der den Port regelmäßig abfragt. Basierend auf der Änderung der Daten wird dieses Ereignis das Ereignis auslösen, das von den konsumierenden Anwendungen behandelt wird

2
Manish Dalal

Könnte sein:

   public async Task Poll(Func<bool> condition, TimeSpan timeout, string message = null)
    {
        // https://github.com/dotnet/corefx/blob/3b24c535852d19274362ad3dbc75e932b7d41766/src/Common/src/CoreLib/System/Threading/ReaderWriterLockSlim.cs#L233 
        var timeoutTracker = new TimeoutTracker(timeout);
        while (!condition())
        {
            await Task.Yield();
            if (timeoutTracker.IsExpired)
            {
                if (message != null) throw new TimeoutException(message);
                else throw new TimeoutException();
            }
        }
    }

Schauen Sie in SpinWait oder in Task.Delay Interna.

0
Dzmitry Lahoda