2009-12-15 69 views
1

在我用WPF和C#构建的.NET应用程序中,我使用AsyncMethodCaller调用异步函数。在回调中,我想更新GUI中的一些数据,但我不被允许,因为它由主线程拥有。我该如何做?异步函数 - 使用主线程拥有的对象回调

  • 在主线程上调用更新?怎么样?
  • 将一个对象(例如ViewModel)作为状态传递给回调函数并在其上更新数据 - 这又是绑定到GUI的?
  • 还有其他的一些方法吗?

什么是处理这种常见的推荐方式?

给出的运行时错误是:因为不同的线程拥有它

调用线程不能访问该对象。

回答

3

您需要使用Dispatcher调用该方法,调用Dispatcher.Invoke方法。 这个MSDN article解释了如何更详细地从异步操作更新WPF中的UI。

0

我尝试传递ViewModel对象asyncState,使回调可以访问此对象。回调通常会使用从异步函数调用接收到的值更新某个属性。无论如何,ViewModel最终会成为我想要进行状态更新的地方。这是处理它的正确方法吗?或者我应该总是使用Dispatcher.Invoke?

视图模型:

public class MyViewModel : BaseViewModel 
{ 
    public int Result 
    { 
     get { return _result; } 
     set 
     { 
      _result = value; 
      this.RaisePropertyChanged("Result"); 
     } 
    } 
} 

调用函数:

caller.BeginInvoke(num1, num2, new AsyncCallback(CallbackMethod), _myViewModel); 

回调更新视图模型:

private void CallbackMethod(IAsyncResult ar) 
{ 
    var result = (AsyncResult)ar; 
    var caller = (AsyncMethodCaller)result.AsyncDelegate; 
    var vm = ar.AsyncState as MyViewModel; 
    int returnValue = caller.EndInvoke(ar); 
    vm.Result = returnValue; 
} 
2

Bambuska,

使用Dispatcher真的很多EA比你想象的要更高。请看看我的代码:

public class MyViewModel : BaseViewModel  
{  
    public int Result  
    {  
     get { return _result; }  
     set  
     {  
      _result = value;  

      Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new WorkMethod(delegate 
       { 
        this._result = SampleMethodChangingResult(); 
       })); 

      this.RaisePropertyChanged("Result");  
     }  
    }  
} 

这应该工作(它在我的情况)。无论如何,请告知我。

+0

谢谢!您在这里展示的原理可以帮助我,尽管代码似乎并不“开箱即用”。你真的会从viewmodel调用吗?这意味着你必须传递viewModel对象作为状态,因为如果你属于主线程,你无法访问它。所以我假设你会直接从回调中调用? – stiank81 2009-12-16 07:58:13

+0

这是我从回调中做的。请注意,我不能使用Dispatcher.CurrentDispatcher.Invoke,因为我需要属于主线程的一个 - 我假设..? (DispatcherPriority.Normal,(ThreadStart)(()=> UpdateSomething(returnValue))); – stiank81 2009-12-16 07:59:21

+0

我想你可以做到这一点,但你为什么坚持传递VM对象?你绝对可以在vm对象内执行我的代码,并且由于vm作为DataContext绑定到一个视图对象,它肯定是在主线程中执行的。 – 2009-12-16 08:59:52