0

これは、私が使用しようとしている非同期応答を持つ 3 層アプリケーションのモデルです。

  • GUI
  • バックエンド
  • リモートサーバー

GUI:

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

バックエンド (内部変数binReaderおよびconnection を使用)

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 は < Key, Action > のペアをスレッドセーフなディクショナリに追加します。別のワーカー スレッドがネットワーク ストリーム メッセージ (メッセージ ヘッダー) から読み取り、メッセージ ヘッダーにある文字列 cmd に従ってアクションを呼び出します。

今質問:

  • 定期的な更新 (単一のコールバックではない) のために GUI 要素をサブスクライブする必要がある場合、同じレベルの簡潔さに到達することは可能ですか?
4

1 に答える 1

1

さて、あなたは持っているものを取り、ループに入れることができます。例えば:

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

私は個人的に「無限の非同期」ループが好きではありませんが。ループを停止する唯一の方法は、例外 (エラーまたはキャンセル) をスローすることです。

Rx ライブラリはサブスクリプションに適しています。高レベルの「簡潔さ」が得られますが、学習曲線は急勾配になります。

すべてのサブスクリプション ロジックを Model/ViewModel にラップすることもできます。これは、同じ概念値を「更新」する場合に特に意味があります。その場合、StartReadingModel/ViewModel のメソッドになります。async(無限非同期ループの場合) または(Rx の場合) を使用ObserveOnして UI スレッドに更新をもたらし、次に標準のINotifyPropertyChanged/ObservableCollectionを使用して UI を間接的に更新します。

于 2012-01-02T19:35:55.073 に答える