C # simple background thread

I am looking for an easy way to do a task in the background, and then update something (along the main thread) when it is completed. It is in the low-level model class, so I cannot invoke InvokeOnMainThread since I don't have NSObject. 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 works fine, but

1) Is this the best (easiest) way?

2) I am worried about a local variable:

 Item{} items=null 

What stops extinction when a method returns before the background thread completes?

Thanks.

+7
source share
4 answers

I think your method slightly violates the principle of single responsibility , because it does too much.

First of all, I suggest changing CreateItems to return Task instead of wrapping it in GetItemsAsync :

 public Task<Item[]> CreateItems(CancellationToken token) { return Task.Factory.StartNew(() => // obtaining the data... {}); } 

CancellationToken is optional, but can help you if you can cancel this lengthy operation.

With this method, you can completely remove GetItemsAsync because it is so easy to process the results with 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 will get a clearer code with one responsibility. The Task class itself is an ideal tool for representing an asynchronous operation as the first object of a class . Using the proposed technique, you can easily make fun of your current implementation with fake behavior for unit testing without changing the code of your clients.

+2
source

Something like that:

  public void GetItemsAsync(Action<Item[]> handleResult) { int Id = 11; Task<Item[]> task = Task.Factory.StartNew(() => CreateItems(Id)); // May take a second or two task.ContinueWith(t => handleResult(t.Result), TaskScheduler.FromCurrentSynchronizationContext()); } 
+2
source

Your code looks good.

This is a great example of using async / await , if you can use C # 5, but if not, you should write it the same way as with the sequel.

The items variable is fixed in your lambdas, so that is also very good.

When you write a lambda that uses an external variable, the C # compiler creates a class containing the variable. This is called closure and means you can access the variable inside your lambda.

+1
source

Here is a more pleasant soul:

  public void GetItemsAsync(Action<Item[]> handleResult) { var task = Task.Factory.StartNew<Item[]>(() => { return this.CreateItems(); // May take a second or two }); task.ContinueWith(delegate { handleResult(task.Result); }, TaskScheduler.FromCurrentSynchronizationContext()); } 
+1
source

All Articles