2009-07-18 39 views
1

我是一个WCF服务的新手,我试图弄清楚当我异步调用我的WCF服务时是否有更好的方式来更新WPF UI元素(如Label控件)。有没有更好的方式来使用分派器更新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); 

    } 

正如你所看到的,我更新label1.Content,由一个AsyncCallback获得。

我的问题是,是否有更好或更正确的方法刷新此异步回调操作内的UI控件?

在此先感谢!

回答

3

Dispatcher.Invoke是更新您的用户界面的好方法。用户界面操作必须由UI线程执行,调度员负责此操作。

您可以通过使用Lambda表达式使你的代码短一点:

Dispatcher.Invoke((Action<string>) ((data) => { label1.Content = data; })); 

我也建议把代理在使用语句,所以这将使它:

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); 
+0

实际上,WCF是我知道你不应该在哪里实现'using'块的一种情况。请参阅“不可饶恕:WCF Gotcha#1 - Jesse Ezell博客”,网址为http://weblogs.asp.net/jezell/archive/2008/07/02/indisposable-wcf-gotcha-1.aspx – 2009-07-19 02:42:38

+0

哇,但是我明白正确地说你根本不应该使用Close方法,而是使用Abort()方法?这不是一个真正具体的使用问题,而是微软更奇怪的实现。 – Zyphrax 2009-07-19 11:08:56

+1

不,关闭是可以的。问题是:在“使用”中抛出异常1;处置被称为;处理通话“关闭”;关闭抛出异常2.异常1丢失。在我发布的博客上的模式的作品。而且,是的,这是微软的糟糕设计。他们错过了一个。我发现Don Box的一句话说他被问到在这种情况下被调用时Close是否可以抛出,并且他认为它没问题,因为你已经处理了一个异常。他错过了我们正在处理一个_different_异常。 – 2009-07-19 20:41:34

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,因为它无需连接后台线程。

相关问题