Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# simple background thread

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.

like image 722
Bbx Avatar asked Nov 27 '12 09:11

Bbx


1 Answers

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.

like image 134
Sergey Teplyakov Avatar answered Oct 10 '22 11:10

Sergey Teplyakov