2016-08-09 48 views
0

我有一個來自RS-232端口的輸入流和一個使用Rx流的串行端口的命令隊列。我簡化了我的代碼如下:使用流的請求/響應

void Init() 
{ 
    SerialPort srl; 

    ... // open serial port 

    IObservable<string> obInput = 
     Observable.FromEventPattern< 
     SerialDataReceivedEventHandler, 
     SerialDataReceivedEventArgs> 
     (
      handler => srl.DataReceived += handler, 
      handler => srl.DataReceived -= handler 
     ).SelectMany(_ => 
     { 
     List<string> ret; 
     ... //extract messages 
     return ret; 
     }).Publish().Refcount(); 

    obCommandOk = 
     obInput 
     .Where(msg => msg == "OK" || msg == "KO"); 

    var sAction = new Subject<string>(); 
    var sCommandOk = new Subject<Tuple<string,bool>>(); 

    sAction 
     .Do(srl.WriteLine) 
     .Zip(obCommandOk, (cmd, result) => 
     { 
     if (result == "OK") 
      sCommandOk.OnNext(Tuple.Create(cmd, true)) 
     else 
      sCommandOk.OnNext(Tuple.Create(cmd, false)) 
     }); 
} 

async bool Command(string cmd) 
{ 
    sAction.OnNext(cmd); 

    return 
     await sCommandOk 
     .Where(t => t.Item1 == cmd) 
     .Select(t => t.Item2) 
     .FirstAsync(); 
} 

有時會發生OnNext後的結果已經被推向sCommandOk,所以我失去它。

你能否建議我一個更好的方法來避免失去反應?

+1

我們能否旨在提供http://stackoverflow.com請/幫助/麥克風?當然,我知道它是僞代碼,但它與編譯的真正的C#大約有5個變化。 –

+0

@LeeCampbell推斷你從我的代碼中請求的內容是相當困難的,但我寫了一些東西在這裏編譯https://gist.github.com/zpul/b7a59e559e523a8a3b1077b1ec8013ef(對於SO來說太大) – zpul

+0

你真的不應該使用來自'SelectMany'的外部可變緩衝區,這真是一個非常糟糕的主意。你將能夠保證對其內容完全沒有任何影響。 – TheInnerLight

回答

0

在您的Command方法中您有競爭狀態。 您推動Action,然後訂閱結果。 如果結果很快,那麼你就把它鬆開。

這裏的小改變可以減輕:

async Task<bool> Command(string cmd) 
{ 
    var result = sCommandOk 
     .Where(t => t.Item1 == cmd) 
     .Select(t => t.Item2) 
     .FirstAsync(); 

    sAction.OnNext(cmd); 

    return await result; 
} 

我想你可以進一步優化通過去除sCommandOk主題一起

async Task<bool> Command(string cmd) 
{ 
    var result = obInput 
     .Where(t => t.Item1 == cmd) 
     .Select(t => t.Item2) 
     .FirstAsync(); 

    sAction.OnNext(cmd); 

    return await result; 
} 
+0

不幸的是,我已經嘗試過這種方法,問題依然存在。我現在發現的唯一解決方案是與命令一起傳遞一個結果變量,如果在設置了OnNext之後,我已經有了結果,否則我將等待。這是一個非常糟糕的,所以我不喜歡它。 – zpul