2015-07-21 78 views
0

我正在嘗試編寫一個代表與設備通過RS232連接進行通信的類。這個設備可以被讀取和寫入,這可以由多個線程完成。使用多線程使用的RS232?

到目前爲止,我選擇將該類設置爲單例類,因爲它有意義,只有一個連接到設備應該永遠存在。我還實施了兩個接口IDataProviderIDataConsumer。這些只是定義了方法Boolean ReadData(out Object readData, params Object[] args)WriteData(Object inData, params Object[] args)。隨着界面我也寫了RS232Device。這實現了將端口Open(),Close(),Read()Write()的方法。

以下是我的課程概述。

public class DeviceIO : RS232Device, IDataProvider, IDataConsumer 
{ 
    public static DeviceIO Instance { get { return lazyInstance.Value; } } 
    private static readonly Lazy<DeviceIO> lazyInstance 
     = new Lazy<DeviceIO>(() => new DeviceIO()); 

    private DeviceIO() : base() {} 

    public void ConfigurePort(SerialPortConfig inConfig) 
    { 
     Configure(inConfig); 
    } 

    public Boolean ReadData(out Object readData, params Object[] args) 
    { 
     readData = null; 
     return false; 
    } 

    public Boolean WriteData(Object inData, params Object[] args) 
    { 
     return false; 
    } 
} 

我現在的問題是我如何使這個線程安全。我會假設在ReadDataWriteData之內,我會鎖定Object的某個實例。這就是我需要做的一切嗎?基本上就像下面的修改一樣?

我可以將下面的Instance分配給各種線程,並且在兩個線程可能嘗試同時寫入設備時沒有任何問題嗎?

public class DeviceIO : RS232Device, IDataProvider, IDataConsumer 
{ 
    public static DeviceIO Instance { get { return lazyInstance.Value; } } 
    private static readonly Lazy<DeviceIO> lazyInstance 
     = new Lazy<DeviceIO>(() => new DeviceIO()); 

    private static readonly Object Schlage = new Object(); 

    private DeviceIO() : base() {} 

    public void ConfigurePort(SerialPortConfig inConfig) 
    { 
     lock(Schlage) 
     { 
      Configure(inConfig); 
     } 
    } 

    public Boolean ReadData(out Object readData, params Object[] args) 
    { 
     lock (Schlage) 
     { 
      readData = null; 
      return false; 
     } 
    } 

    public Boolean WriteData(Object inData, params Object[] args) 
    { 
     lock (Schlage) 
     { 
      return false; 
     } 
    } 
} 
+0

這是正確的。注意:你的'Schlage'變量不一定是'static'。 –

+0

還有一個問題,大多數情況下,當你試圖查詢串口設備時,你首先向RS232寫入數據,然後讀取一行數據。如果我輸入'ReadData'方法並獲得一個鎖,我可以調用'WriteData'而不是自己死鎖嗎? – KDecker

+0

一旦鎖定建立,'lock'只會阻止** OTHER **線程進入。從**相同的**線程內,從ReadData()到WriteData()不會阻塞,並且不會導致問題。 –

回答

1

我建議通過實現消息隊列模式來更好地服務這種類型的場景。在這裏,任何需要使用RS232設備的代碼都會將請求排入隊列,然後等待回覆或反應。同時,恰好一個線程將服務於該隊列的業務端,一次一個地從隊列中取出隊列,通過從RS232端口發送和/或接收信息來執行它,然後繼續下一個排隊的消息。

這有助於簡化代碼流,並有助於防止死鎖。所有實際訪問RS232資源的代碼都只在一個線程上執行(您的隊列服務線程)。至於其他所有線程,他們只需將他們的請求發送到隊列 - 一個非常快速的操作,然後檢查他們的響應。實現這個

一種方法是:

_myMessageQueue = new ConcurrentQueue<Rs232Message>(); 

到消息隊列發佈新的消息正是如此:

_myMessageQueue.Enqueue(message); 

和您檢索排隊的消息:

bool isOk = _myMessageQueue.TryDequeue(out message); 
+0

我喜歡這個想法,並最終找到了一種解決方案,有點類似於這個和我在OP中提出的建議。在過去的兩年中,沒有人想回答這個問題,你可以享用雞肉晚餐。 – KDecker