2016-08-09 103 views
1

Ich habe ein Varsity-Projekt, bei dem ich einen RFID-Leser im Hintergrund verwenden muss, um den Mitarbeiter-Ein-/Ausgang zu verfolgen. Die Vordergrund-winform-GUIs befassen sich mit alltäglichen Transaktionen wie Bestellungen, Angeboten usw. Daher muss ich in der Lage sein, das Programm ohne Unterbrechung zu verwenden und gleichzeitig die Mitarbeiter im Kommen und Gehen zu verfolgen. Ich habe Hintergrundarbeiter angeschaut, eine Art neues Profil und Input-Grabbing. Aber ich kann einfach nichts finden, was funktionieren wird. Der RFID-Leser fungiert als Tastatur und ich kann seinen Namen bekommen. Raw InputUSB-RFID-Leser-Eingang mit Hintergrundverarbeitung verwenden

RFID Details mit: RFID Reader Details

Um zu klären, muss der Benutzer in der Lage sein, das Programm (mehr Formen) ohne Unterbrechung zu verwenden, während jede Eingabe von dem RFID-Lesegerät muss in einer Hintergrund-Liste aufgenommen werden.

Ich bin neu im Hintergrund Arbeiter, Multi-Threading und Eingabe Grabbing, so dass ich einige detaillierte Hilfe zu schätzen wissen. Bitte fragen Sie auch, ob Sie mehr Details von meiner Seite benötigen.

+0

Haben Sie einige Codes haben? Ohne Codes ist dies zu weit gefasst ... –

+0

Haben Sie bereits einige RFIDs in C# erfolgreich mit Ihrem Gerät gelesen? Dann poste bitte den Code, den du bereits ausprobiert hast. – BoeseB

Antwort

0

Multi Threading ist nicht sehr einfach. BackgroundWorker ist etwas einfacher auf der GUI, aber es ist immer noch schwierig, von der Hintergrundaufgabe auf die GUI zuzugreifen. Warum nicht zuerst mit der Task/Await versuchen? Dies vermeidet Multithreading und kann immer noch zwei Aufgaben ausführen.

+0

Vorausgesetzt, er verwendet .NET 4.5 unterstützt async/warten. Wenn er frühere .NET-Versionen verwendet, benötigt er eine Bibliothek wie AsyncBridge. Auch wenn Async/await und Task die parallele Programmierung vereinfachen, ist es immer noch Multithreading. Bevor ich mit Multithreading den RFID-Reader abfragen kann, würde ich vorschlagen, auf das Empfangene Ereignis des USB-Geräts zu reagieren, wenn die verwendete USB-Lib dies unterstützt. – BoeseB

+1

Wahr. Ich würde nicht mit alten Versionen von .Net gehen.Die Aufgabe hat mich eine Weile gedauert, um die Konzepte zu bekommen, aber jetzt mag ich es viel besser als echtes Multithreading. – Roland

1

Der RFID-Leser, den ich hier habe, ein NordicID Sampo kommt mit einer API, die einen Thread hochfeuert, der die Daten liest. Sie können darauf aufbauen, indem Sie einen Task erstellen, der Daten aus einem von diesem Thread hinzugefügten Puffer liest. Dann können Sie diese Daten an ein Formular weiterleiten oder eine E-Mail senden oder was auch immer.

Ihr Scanner hat wahrscheinlich einen ähnlichen Mechanismus.

Beispiel: StartStreaming ist ein Wrapper um die API des Geräts, der den Thread auslöst, der die Daten des Geräts liest.

class RFIDReader : IDisposable 
    { 
     public void StartStreaming() 
     { 
      if (RFID_ConnectSerialPort(mAPIHandle, 4, 115200) == 0 || RFID_ConnectAutoUSB(mAPIHandle) == 0) 
      { 
       RFID_StartInventoryStreaming(
        (value, antenna) => { 
         mAntennas[antenna].Add(value); 
        }); 
      } 
     } 
/////// MORE FUNCTIONS 
    } 

Client-Code, der seine eigene Aufgabe löst und in regelmäßigen Abständen für die Datenprüfung:

static void Main(string[] args) 
{ 
    Action a = new Action(() => 
    { 
     using (RFIDReader scanner = new RFIDReader()) 
     { 
      scanner.StartStreaming(); 

      while (true) 
      { 
       foreach (string s in scanner.GetData(0)) 
       { 
        WriteLine($"antenna0: {s}"); 
       } 
       Thread.Sleep(1000); 
      } 
     } 
    }); 
    Task t = Task.Factory.StartNew(a); 

    t.Wait(); 
} 
+1

Verwenden Sie möglicherweise [Task.ConfigureAwait (false), um Deadlocks zu vermeiden] (https://blog.ciber.no/2014/05/19/using-task-configureawaitfalse-to-prevent-deadlocks-in-async-code/) . – BoeseB

+0

Dann brauchen Sie .NET 4.5, im Produktionscode würde ich den SynchronizationContext speichern und diesen für die Aktualisierung der GUI-Nut verwenden, ja in 4.5 rufen Sie einfach ConfigureWait – Laurijssen

1

Wenn Sie mit LibUsbDotNet Sie auf der DataReceivedEvent reagieren könnten. Sie vermeiden also, während der Abfrage nach neuen Daten zu blockieren. Wenn Sie den Polling-Approach gewählt haben, hat @ Servé Ihnen bereits gezeigt, wie Sie es an eine andere Aufgabe senden können, um den Haupt-Thread nicht zu blockieren.

Hier ist also die vorgeschlagene Lösung mit dem DataReceivedEvent.

das USB-Gerät initialisieren:

IUsbDevice wholeUsbDevice = PhysicalLibUSBDevice as IUsbDevice; 
    if (!ReferenceEquals(wholeUsbDevice, null)) 
    { 
     // This is a "whole" USB device. Before it can be used, 
     // the desired configuration and interface must be selected. 

     // Select config #1 
     wholeUsbDevice.SetConfiguration(1); 

     // Claim interface #0. 
     wholeUsbDevice.ClaimInterface(0); 
    } 


    // Create the reader and writer streams 
    _libUsbReader = PhysicalLibUSBDevice.OpenEndpointReader(LibUsbDotNet.Main.ReadEndpointID.Ep01); 
    _libUsbWriter = PhysicalLibUSBDevice.OpenEndpointWriter(LibUsbDotNet.Main.WriteEndpointID.Ep02); 

    _libUsbReader.DataReceived += OnDataReceived; 
    _libUsbReader.DataReceivedEnabled = true; 
    _libUsbReader.ReadThreadPriority = System.Threading.ThreadPriority.Highest; 
    _libUsbReader.ReadBufferSize = 32; 

die Eventhandler definieren:

private void OnDataReceived(object sender, EndpointDataEventArgs e) 
{ 
    //Use the Buffer and Count Properties of the EventArgs to get the received data   
    Console.WriteLine("Data received"); 
}