使用异步扩展
问题描述:
这对于异步响应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元素?
答
嗯,你可以只取你所拥有的,把在进入一个循环,例如:
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。
谢谢。这种循环是一种可能的解决方案,但你是对的:我的确将它作为临时解决方法。 我会研究Rx,但我开始怀疑TPL DataFlow是否可以提供与我样本中的样式相一致的解决方案。 – 2012-01-02 22:37:00
Stephen在深入研究Rx后,同意你的回答确实完整,并为我的问题提供了最一致的答案。 谢谢! – 2012-01-17 17:38:43