2012-01-02 68 views
0

這對於異步響應3層應用程序,我想使用該模型實現的GUI監聽器(訂閱):使用異步擴展

  • GUI
  • 後端
  • 遠程服務器

GUI:

private async void readFloatButton_Click(object sender, RoutedEventArgs e) 
{ 
    FloatValueLabel.Content = (await srvProtocol.ReadFloat("ReadFloatX")).ToString(); 
} 

後端(使用內部變量 binReader連接

public Task<float> ReadFloat(string cmd) 
{ 
    var tcs1 = new TaskCompletionSource<float>(); 
    var floatTask = tcs1.Task;  
    RegisterResponse(cmd, 
        () => 
        tcs1.SetResult(_binReader.ReadSingle()); 
        ); 
    // We are ready: now send request to server(assuming that this is a quick operation) 
    connection.Send(cmd); 
    return floatTask; 
} 

這裏RegisterResponse增加了<重點,動作>對某些線程安全的字典。 另一個工作線程從網絡流中讀取消息(消息頭)並根據消息頭中的字符串cmd調用動作。

現在的問題:

  • 是有可能達到簡潔同一水平的時候,我需要認購定期更新(不是一個單一的回調)GUI元素?

回答

1

嗯,你可以只取你所擁有的,把在進入一個循環,例如:

private async void StartReading() 
{ 
    while (true) 
    { 
    FloatValueLabel.Content = (await srvProtocol.ReadFloat("ReadFloatX")).ToString(); 
    await Task.Delay(1000); 
    } 
} 

雖然我個人不喜歡的「無限異步」循環。停止循環的唯一方法是引發異常(錯誤或取消)。

Rx library更適合訂閱。它允許高水平的「簡潔」,但具有更陡峭的學習曲線。

您也可以將所有訂閱邏輯封裝到Model/ViewModel中。這在處理「更新」相同的概念價值時尤其有意義。在這種情況下,StartReading將是您的Model/ViewModel上的一種方法。它將使用async(用於無限異步循環)或ObserveOn(用於Rx)將更新引入UI線程,然後使用標準的INotifyPropertyChanged/ObservableCollection間接更新UI。

+0

謝謝。這種循環是一種可能的解決方案,但你是對的:我的確將它作爲臨時解決方法。 我會研究Rx,但我開始懷疑TPL DataFlow是否可以提供與我樣本中的樣式相一致的解決方案。 – 2012-01-02 22:37:00

+0

Stephen在深入研究Rx後,同意你的回答確實完整,併爲我的問題提供了最一致的答案。 謝謝! – 2012-01-17 17:38:43