使用异步扩展在GUI中实现侦听器(预订)

时间:2012-01-02 19:09:20

标签: c# asynchronous subscription async-await

这是我试图使用的具有异步响应的3层应用程序的模型:

  • 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添加&lt;关键,行动&gt;配对一些线程安全的字典。 另一个工作线程从网络流消息中读取消息(消息头),并根据消息头中找到的字符串cmd调用操作。

现在的问题是:

  • 当我需要订阅GUI元素进行定期更新(而不是单个回调)时,是否可以达到相同的简洁程度?

1 个答案:

答案 0 :(得分: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。