I'm working on an app and trying to do everything nice and best practice; here's the code that doesn't do what I want it to:
async public Task DoStuff()
{
DispatcherAdapter.Current.BeginInvoke(() => { myObject.SomeProperty = "new value"; });
await DatabaseAdapter.Current.SaveItem(TableName, myObject);
}
The code above doesn't save the item to the database with the updated property value, and I imagine this is because BeginInvoke() doesn't necessarily finish before my awaited async method does its work. DispatcherAdapter just uses Deployment.Current.Dispatcher in the background, like this:
public override void BeginInvoke(Action a)
{
Deployment.Current.Dispatcher.BeginInvoke(a);
}
Here's what I've looked into, and doesn't work:
- awaiting the BeginInvoke() call - wont work because it doesn't return Task, and it still drills down to not being able to tell when Dispatcher.BeginInvoke actually finishes
- trying to work with the DispatcherOperation object returned from BeginInvoke() - the Completed event that's available in normal .NET is not available for Windows Phone 8
using SynchronizationContext.Send() - DispatcherSynchronizationContext.Current is always null, so doesn't work...see irrelevant code below:
public async override Task Invoke(Action a) { await Task.Factory.StartNew(() => { DispatcherSynchronizationContext.Current.Send(new SendOrPostCallback(delegate { a.Invoke(); }), null); }); }
Basically, how can I avoid invalid-cross-thread access AND ensure code runs in a specific order within an asynchronous method in Windows Phone 8? I guess I could move the .SaveItem to go within the BeginInvoke...but it feels like a cheat way out, I still can't await that BeginInvoke call (which makes putting it in an async method pretty pointless) and it would be nice to know what I should be doing / other people have done in this situation.