我正在开发一个应用程序,并尝试做一切美好和最佳实践;这是没有执行我想要的代码:
async public Task DoStuff()
{
DispatcherAdapter.Current.BeginInvoke(() => { myObject.SomeProperty = "new value"; });
await DatabaseAdapter.Current.SaveItem(TableName, myObject);
}
上面的代码没有使用更新的属性值将项目保存到数据库,我想这是因为在我等待的异步方法完成其工作之前,BeginInvoke()不一定完成。 DispatcherAdapter只在后台使用Deployment.Current.Dispatcher,如下所示:
public override void BeginInvoke(Action a)
{
Deployment.Current.Dispatcher.BeginInvoke(a);
}
这是我所看到的,但不起作用:
using SynchronizationContext.Send() - DispatcherSynchronizationContext.Current始终为null,因此不起作用...请参阅下面的无关代码:
public async override Task Invoke(Action a)
{
await Task.Factory.StartNew(() => { DispatcherSynchronizationContext.Current.Send(new SendOrPostCallback(delegate { a.Invoke(); }), null); });
}
基本上,如何避免无效的跨线程访问并确保代码在Windows Phone 8中的异步方法中以特定顺序运行?我想我可以移动.SaveItem进入BeginInvoke ...但感觉就像一个骗子出路,我仍然不能等待BeginInvoke调用(这使得它在异步方法中毫无意义)并且它将是很高兴知道我应该做什么/其他人在这种情况下做了什么。
答案 0 :(得分:2)
最简单的方法是从UI线程调用async
方法。然后你可以这样做:
public async Task DoStuffAsync()
{
myObject.SomeProperty = "new value";
await DatabaseAdapter.Current.SaveItem(TableName, myObject);
}
如果您的async
方法需要在后台线程上执行某些操作,请将其包装在Task.Run
中。
答案 1 :(得分:1)
我最终创建了自己的DispatcherSynchronizationContext,一切似乎都有效:
public async override Task Invoke(Action a)
{
DispatcherSynchronizationContext dsc = new DispatcherSynchronizationContext(Deployment.Current.Dispatcher);
await Task.Factory.StartNew(() => { dsc.Send(new SendOrPostCallback(delegate { a.Invoke(); }), null); });
}
我仍然不确定这是否是这样做的推荐方法,或者以这种方式使用DispatcherSynchronizationContext有任何问题...但是我可以等待这个影响UI线程的帮助方法,所以这是一个启动...