1

我是 WCF 服务的新手,我试图弄清楚当我异步调用我的 WCF 服务时是否有更好的方法来更新 WPF UI 元素(如标签控件)。

这是一段代码:

    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 控件?

提前致谢!

4

2 回答 2

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);
于 2009-07-18T18:12:57.023 回答
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,因为它不需要后台线程。

于 2009-07-19T20:33:49.263 回答