2012-01-02 66 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