在我用WPF和C#构建的.NET应用程序中,我使用AsyncMethodCaller调用异步函数。在回调中,我想更新GUI中的一些数据,但我不被允许,因为它由主线程拥有。我该如何做?异步函数 - 使用主线程拥有的对象回调
- 在主线程上调用更新?怎么样?
- 将一个对象(例如ViewModel)作为状态传递给回调函数并在其上更新数据 - 这又是绑定到GUI的?
- 还有其他的一些方法吗?
什么是处理这种常见的推荐方式?
给出的运行时错误是:因为不同的线程拥有它
调用线程不能访问该对象。
在我用WPF和C#构建的.NET应用程序中,我使用AsyncMethodCaller调用异步函数。在回调中,我想更新GUI中的一些数据,但我不被允许,因为它由主线程拥有。我该如何做?异步函数 - 使用主线程拥有的对象回调
什么是处理这种常见的推荐方式?
给出的运行时错误是:因为不同的线程拥有它
调用线程不能访问该对象。
您需要使用Dispatcher调用该方法,调用Dispatcher.Invoke方法。 这个MSDN article解释了如何更详细地从异步操作更新WPF中的UI。
我尝试传递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;
}
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");
}
}
}
这应该工作(它在我的情况)。无论如何,请告知我。
谢谢!您在这里展示的原理可以帮助我,尽管代码似乎并不“开箱即用”。你真的会从viewmodel调用吗?这意味着你必须传递viewModel对象作为状态,因为如果你属于主线程,你无法访问它。所以我假设你会直接从回调中调用? – stiank81 2009-12-16 07:58:13
这是我从回调中做的。请注意,我不能使用Dispatcher.CurrentDispatcher.Invoke,因为我需要属于主线程的一个 - 我假设..? (DispatcherPriority.Normal,(ThreadStart)(()=> UpdateSomething(returnValue))); – stiank81 2009-12-16 07:59:21
我想你可以做到这一点,但你为什么坚持传递VM对象?你绝对可以在vm对象内执行我的代码,并且由于vm作为DataContext绑定到一个视图对象,它肯定是在主线程中执行的。 – 2009-12-16 08:59:52