I am looking for a simple way to do a task in background, then update something (on the main thread) when it completes. It's in a low level 'model' class so I can't call InvokeOnMainThread as I don't have an NSObject around. I have this method:
public void GetItemsAsync(Action<Item[]> handleResult)
{
Item[] items=null;
Task task=Task.Factory.StartNew(() =>
{
items=this.CreateItems(); // May take a second or two
});
task.ContinueWith(delegate
{
handleResult(items);
}, TaskScheduler.FromCurrentSynchronizationContext());
}
This seems to work OK, but
1) Is this the best (simplest) way?
2) I'm worried about the local variable:
Item{} items=null
What stops that disappearing when the method returns before the background thread completes?
Thanks.
I think your method slightly violates a Single Responsibility Principle, because it doing too much.
First of all I suggest to change CreateItems
to return Task
instead of wrapping it in the GetItemsAsync
:
public Task<Item[]> CreateItems(CancellationToken token)
{
return Task.Factory.StartNew(() =>
// obtaining the data...
{});
}
CancellationToken is optional but can help you if you able to cancel this long running operation.
With this method you can remove GetItemsAsync
entirely because its so simple to handle results by your client without passing this delegate:
// Somewhere in the client of your class
var task = yourClass.CreateItems(token);
task.ContinueWith(t =>
// Code of the delegate that previously
// passed to GetItemsAsync method
{}, TaskScheduler.FromCurrentSynchronizationContext());
Using this approach you'll get more clear code with only one responsibility. Task class itself is a perfect tool for representing asynchronous operation as a first class object. Using proposed technique you can easily mock you current implementation with a fake behavior for unit testing without changing your clients code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With