我是WCF服务的新手,我正在试图弄清楚当我异步调用我的WCF服务时是否有更好的方法来更新WPF UI元素(比如Label控件)。
这是一段代码:
private void button1_Click(object sender, RoutedEventArgs e)
{
int result;
CalculatorServiceClient proxy = new CalculatorServiceClient();
AsyncCallback addOperation = (async_result) =>
{
result = proxy.EndAdd(async_result);
Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(
delegate()
{
label1.Content = result.ToString();
}
)
);
proxy.Close();
};
proxy.BeginAdd(Convert.ToInt32(txtNumber1.Text), Convert.ToInt32(txtNumber2.Text), addOperation, null);
}
正如您所看到的,我正在使用AsyncCallback获取的异步结果更新label1.Content。
我的问题是,是否有更好或更正确的方法来刷新此异步回调操作中的UI控件?
提前感谢!
答案 0 :(得分:3)
Dispatcher.Invoke是更新UI的好方法。 UI操作必须由UI线程执行,Dispatcher负责处理此事。
使用Lambda表达式可以缩短代码:
Dispatcher.Invoke((Action<string>) ((data) => { label1.Content = data; }));
我还建议将代理放在Using语句中,这样就可以了:
int result = 0;
using (CalculatorServiceClient proxy = new CalculatorServiceClient()) {
AsyncCallback callback = new AsyncCallback((asyncResult) => {
result = proxy.EndAdd(asyncResult);
Dispatcher.Invoke((Action<string>) ((data) => { label1.Content = data; }));
});
proxy.BeginAdd(Convert.ToInt32(txtNumber1.Text), Convert.ToInt32(txtNumber2.Text), callback, null);
}
或者如果你喜欢简短:
int result = 0;
using (CalculatorServiceClient proxy = new CalculatorServiceClient())
proxy.BeginAdd(Convert.ToInt32(txtNumber1.Text), Convert.ToInt32(txtNumber2.Text), new AsyncCallback((asyncResult) => {
result = proxy.EndAdd(asyncResult);
Dispatcher.Invoke((Action<string>) ((data) => { label1.Content = data; }));
}), null);
答案 1 :(得分:1)
可以做得更短:
using (var proxy = new CalculatorServiceClient())
{
proxy.BeginAdd(
Convert.ToInt32(txtNumber1.Text),
Convert.ToInt32(txtNumber2.Text),
(asyncResult) =>
{
int result = proxy.EndAdd(asyncResult);
Dispatcher.BeginInvoke(
(Action) () => { label1.Content = result; });
},
null);
}
诀窍是,Invoke / BeginInvoke并不意味着你必须显式传递参数,编译器无论如何都要运行它。
你不想使用Invoke,因为它不需要后台线程。