2015-08-21 41 views
0

我寫一個窗口服務的應用程序,能夠從如溫度,壓力等體積傳感器收集數據的創建爲消費者和生產者線程的緩衝...使用隊列C#的.NET

處的頻率的數據被讀取是相當高的,可能有一百個傳感器和接收的數據可能是一個頻率可能是每個傳感器每秒一個..

我需要將此數據存儲到oracle數據庫,原因很明顯不想以如此高的速度擊中數據庫。

因此,我想建立一個緩衝區。

我的計劃是使用標準.NET隊列創建一個緩衝區,線程數保持排隊的數據到隊列中,另一定時器驅動的線程可以繼續寫入定期數據庫。

我想知道的是.. ??這是線程安全嗎 如果不是這樣,創建內存緩衝區的最佳方法是什麼

+3

你可能會想在[線程安全的集合(https://msdn.microsoft.com/en-us/library/dd997305(V = vs.110)的.aspx),特別是ConcurrentQueue讀了。 – Micke

+0

幾年前,我使用[ZeroMQ](http://zeromq.org/)構建了一個類似的解決方案,它負責處理產品問題和併發問題。它的工作,並仍然正常工作! – Micke

+0

當我添加我的解決方案後,我讀了Micke的評論,我認爲你應該首先看看那些:) – mdiehl13

回答

0

要回答你的問題,只要你鎖定了訪問權限,就可以讓多個線程訪問一個常規隊列。

對於我來說,雖然,我沒有使用,想使用隊列,鎖,讓他們線程安全的。我一直在c#中爲我的一個程序做這個。我只是使用一個普通的隊列,然後放置一個更衣室(enqueue,dequeue,count)。如果您只是鎖定訪問權限,則它是完全線程安全的。

我的設置來自教程/例子在這裏:http://www.albahari.com/threading/part2.aspx#_ProducerConsumerQWaitHandle

我的情況比你有點不同,但很相似。對我而言,我的數據可能會非常快速地出現,如果我不排隊,那麼如果多個數據同時進入,我將丟失數據。然後我有一個線程正在運行,緩慢地將項目從隊列中取出並處理它們。該切換使用AutoResetEvent來保存我的工作線程,直到數據準備好處理。在你的情況下,你會使用計時器或定期發生的事情。

我複製/粘貼我的代碼,並試圖更改名稱。希望我沒有完全打破它,因爲錯過了一些名稱變更,但你應該能夠獲得要點。

public class MyClass : IDisposable 
{ 
    private Thread sensorProcessingThread = null; 
    private Queue<SensorData> sensorQueue = new Queue<SensorData>(); 
    private readonly object _sensorQueueLocker = new object(); 
    private EventWaitHandle _whSensorEvent = new AutoResetEvent(false); 

    public MyClass() { 
     sensorProcessingThread = new Thread(sensorProcessingThread_DoWork); 
     sensorProcessingThread.Start(); 
    } 
    public void Dispose() 
    { 
     // Signal the end by sending 'null' 
     EnqueueSensorEvent(null); 
     sensorProcessingThread.Join(); 
     _whSensorEvent.Close(); 
    } 
    // The fast sensor data comes in, locks queue, and then 
    // enqueues the data, and releases the EventWaitHandle 
    private void EnqueueSensorEvent(SensorData wd) 
    { 
     lock (_sensorQueueLocker) 
     { 
      sensorQueue.Enqueue(wd); 
      _whSensorEvent.Set(); 
     } 
    } 

    // When asynchronous events come in, I just throw them into queue 
    private void OnSensorEvent(object sender, MySensorArgs e) 
    { 
     EnqueueSensorEvent(new SensorData(sender, e)); 
    } 
    // I have several types of events that can come in, 
    // they just get packaged up into the same "SensorData" 
    // struct, and I worry about the contents later 
    private void FileSystem_Changed(object sender, System.IO.FileSystemEventArgs e) 
    { 
     EnqueueSensorEvent(new SensorData(sender, e)); 
    } 

    // This is the slower process that waits for new SensorData, 
    // and processes it. Note, if it sees 'null' as data, 
    // then it knows it should quit the while(true) loop. 
    private void sensorProcessingThread_DoWork(object obj) 
    { 
     while (true) 
     { 
      SensorData wd = null; 
      lock (_sensorQueueLocker) 
      { 
       if (sensorQueue.Count > 0) 
       { 
        wd = sensorQueue.Dequeue(); 
        if (wd == null) 
        { 
         // Quit the loop, thread finishes 
         return; 
        } 
       } 
      } 
      if (wd != null) 
      { 
       try 
       { 
        // Call specific handlers for the type of SensorData that was received 
        if (wd.isSensorDataType1) 
        { 
         SensorDataType1_handler(wd.sender, wd.SensorDataType1Content); 
        } 
        else 
        { 
         FileSystemChanged_handler(wd.sender, wd.FileSystemChangedContent); 
        } 
       } 
       catch (Exception exc) 
       { 
        // My sensor processing also has a chance of failing to process completely, so I have a retry 
        // methodology that gives up after 5 attempts 
        if (wd.NumFailedUpdateAttempts < 5) 
        { 
         wd.NumFailedUpdateAttempts++; 
         lock (_sensorQueueLocker) 
         { 
          sensorQueue.Enqueue(wd); 
         } 
        } 
        else 
        { 
         log.Fatal("Can no longer try processing data", exc); 
        } 
       } 
      } 
      else 
       _whWatchEvent.WaitOne(); // No more tasks, wait for a signal 
     } 
    } 

你可能會看到的東西是來自Microsoft的.net的Reactive(Rx)。退房:https://msdn.microsoft.com/en-us/data/gg577611.aspx,頁面底部是一個pdf教程「固化異步藍調」:http://go.microsoft.com/fwlink/?LinkId=208528這是非常不同的東西,但也許你會看到你喜歡的東西。