2016-08-09 108 views
1

我有一个varsity项目,我必须在后台使用RFID阅读器来跟踪员工时钟输入/输出。前台winform GUI处理日常事务,如订单,报价等。因此,我需要能够在不中断的情况下使用该程序,同时保持对来往和离职员工的跟踪。我研究过后台工作人员,一些新的步骤和输入攫取。但我似乎无法找到任何可行的方法。 RFID阅读器充当键盘,我可以得到它的名字。使用Raw Input使用USB RFID阅读器输入和后台处理

RFID细节:RFID Reader Details

为了澄清,用户必须能够使用该程序(多种形式)不中断而从RFID读取器的任何输入必须被记录在一个背景列表。

我是新来的背景工作者,多线程和输入抓取,所以我将不胜感激一些详细的帮助。也请询问你是否需要我的更多细节。

+0

你有一些代码?没有任何代码,这将是太宽泛... –

+0

你已经成功地阅读了C#中的一些RFID与您的设备?然后请发布您已经尝试过的代码。 – BoeseB

回答

0

多线程不是很容易。 BackgroundWorker在GUI上稍微简单一些,但仍然很难从后台任务中访问GUI。为什么不先尝试Task/Await?这避免了多线程,并且仍然可以运行两个任务。

+0

鉴于他正在使用支持异步/等待的.NET 4.5。如果他使用的是早期的.NET版本,他需要像AsyncBridge这样的库。即使Async/await和Task简化了并行编程,它仍然是多线程的。在使用多线程轮询RFID阅读器之前,如果使用的USB lib支持这一点,我会建议尝试对USB设备的接收事件做出反应。 – BoeseB

+1

是的。我不会使用旧版本的.Net。任务花了我一些时间来理解概念,但现在我比真正的多线程更喜欢它了。 – Roland

1

我在这里使用的RFID阅读器,NordicID Sampo带有一个API,它启动一个读取数据的线程。您可以通过创建一个Task来从该线程添加的缓冲区读取数据。然后,您可以将这些数据传递给表单或通过电子邮件发送。

您的扫描仪可能有类似的机制。

示例: StartStreaming是设备API的一个包装,它启动读取设备数据的线程。这激发了自己的任务,并定期检查数据

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 
    } 

客户端代码:

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

考虑使用[Task.ConfigureAwait(false)来避免死锁](https://blog.ciber.no/2014/05/19/using-task-configureawaitfalse-to-prevent-deadlocks-in-async-code/) 。 – BoeseB

+0

然后,您需要.NET 4.5,在生产代码中,我将保存SynchronizationContext并使用它更新4.5中的GUI螺母,只需调用ConfigureWait – Laurijssen

1

如果您正在使用LibUsbDotNet 你可以在DataReceivedEvent反应。因此,您可以在轮询新数据时避免阻塞。如果您选择轮询方法@Servé已经向您展示了如何将其发送给其他任务以避免阻塞主线程。

所以这里是DataReceivedEvent的建议解决方案。

初始化USB设备:

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; 

定义事件处理程序:

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"); 
}