How could I accomplish Node.js like asynchronicity with C#? - c#

I work with Node.js and so I got very used to its 'programming style' and its way to deal with asynchronous operations through higher order functions and callbacks, where most I/O events are handled in a async way by design and if I want to make a sync operation, I need to use Promises or the await shortcut, whereas in synchronous programming languages like Java, C#, C++ apparently I'd have to do the opposite, by somehow telling the compiler that the task I want to achieve must be performed asynchronously. I tried reading through the Microsoft docs and couldn't really understand how to achieve it. I mean, I could use Threads but for the simple task I want to process, exploring Threads is just not worth it for the trouble on guaranteeing thread-safety.
I came across the Task class. So, suppose that I want to run a Task method multiple times in a async way, where the functions are being called in parallel. How can I do this?
private Task<int> MyCustomTask(string whatever)
{
// I/O event that I want to be processed in async manner
}
So basically, I wanted to run this method in 'parallel' without threading.
foreach (x in y)
{
MyCustomTask("");
}

If you don't want to await, you can do something like this.
public class AsyncExamples
{
public List<string> whatevers = new List<string> { "1", "2", "3" };
private void MyCustomTask(string whatever)
{
// I/O event that I want to be processed in async manner
}
public void FireAndForgetAsync(string whatever)
{
Task.Run(
() =>
{
MyCustomTask(whatever);
}
);
}
public void DoParallelAsyncStuff()
{
foreach (var whatever in whatevers)
{
FireAndForgetAsync(whatever);
}
}
}

most I/O events are handled in a async way by design and if I want to make a sync operation, I need to use Promises or the await shortcut
I believe the difference you're expressing is the difference between functional and imperative programming, not the difference between asynchronous and synchronous programming. So I think what you're saying is that asynchronous programming fits more naturally with a functional style, which I would agree with. JavaScript is mostly functional, though it also has imperative and OOP aspects. C# is more imperative and OOP than functional, although it grows more functional with each year.
However, both JavaScript and C# are synchronous by default, not asynchronous by default. A method must "opt in" to asynchrony using async/await. In that way, they are very similar.
I tried reading through the Microsoft docs and couldn't really understand how to achieve it.
Cheat sheet if you're familiar with asynchronous JavaScript:
Task<T> is Promise<T>
If you need to write a wrapper for another API (e.g., the Promise<T> constructor using resolve/reject), then the C# type you need is TaskCompletionSource<T>.
async and await work practically the same way.
Task.WhenAll is Promise.all, and Task.WhenAny is Promise.any. There isn't a built-in equivalent for Promise.race.
Task.FromResult is Promise.resolve, and Task.FromException is Promise.reject.
So, suppose that I want to run a Task method multiple times in a async way, where the functions are being called in parallel. How can I do this?
(minor pedantic note: this is asynchronous concurrency; not parallelism, which implies threads)
To do this in JS, you would take your iterable, map it over an async method (resulting in an iterable of promises), and then Promise.all those promises.
To do the same thing in C#, you would take your enumerable, Select it over an async method (resulting in an enumerable of tasks), and then Task.WhenAll those tasks.
var tasks = y.Select(x => MyCustomTask(x)).ToList();
await Task.WhenAll(tasks);

Related

Chaining arbitrary number of tasks together in C#.NET

What I have
I have a set of asynchronous processing methods, similar to:
public class AsyncProcessor<T>
{
//...rest of members, etc.
public Task Process(T input)
{
//Some special processing, most likely inside a Task, so
//maybe spawn a new Task, etc.
Task task = Task.Run(/* maybe private method that does the processing*/);
return task;
}
}
What I want
I would like to chain them all together, to execute in sequential order.
What I tried
I have tried to do the following:
public class CompositeAsyncProcessor<T>
{
private readonly IEnumerable<AsyncProcessor<T>> m_processors;
//Constructor receives the IEnumerable<AsyncProcessor<T>> and
//stores it in the field above.
public Task ProcessInput(T input)
{
Task chainedTask = Task.CompletedTask;
foreach (AsyncProcessor<T> processor in m_processors)
{
chainedTask = chainedTask.ContinueWith(t => processor.Process(input));
}
return chainedTask;
}
}
What went wrong
However, tasks do not run in order because, from what I have understood, inside the call to ContinueWith, the processor.Process(input) call is performed immediately and the method returns independently of the status of the returned task. Therefore, all processing Tasks still begin almost simultaneously.
My question
My question is whether there is something elegant that I can do to chain the tasks in order (i.e. without execution overlap). Could I achieve this using the following statement, (I am struggling a bit with the details), for example?
chainedTask = chainedTask.ContinueWith(async t => await processor.Process(input));
Also, how would I do this without using async/await, only ContinueWith?
Why would I want to do this?
Because my Processor objects have access to, and request things from "thread-unsafe" resources. Also, I cannot just await all the methods because I have no idea about how many they are, so I cannot just write down the necessary lines of code.
What do I mean by thread-unsafe? A specific problem
Because I may be using the term incorrectly, an illustration is a bit better to explain this bit. Among the "resources" used by my Processor objects, all of them have access to an object such as the following:
public interface IRepository
{
void Add(object obj);
bool Remove(object obj);
IEnumerable<object> Items { get; }
}
The implementation currently used is relatively naive. So some Processor objects add things, while others retrieve the Items for inspection. Naturally, one of the exceptions I get all too often is:
InvalidOperationException: Collection was modified, enumeration
operation may not execute.
I could spend some time locking access and pre-running the enumerations. However, this was the second option I would get down to, while my first thought was to just make the processes run sequentially.
Why must I use Tasks?
While I have full control in this case, I could say that for the purposes of the question, I might not be able to change the base implementation, so what would happen if I were stuck with Tasks? Furthermore, the operations actually do represent relatively time-consuming CPU-bound operations plus I am trying to achieve a responsive user interface so I needed to unload some burden to asynchronous operations. While being useful and, in most of my use-cases, not having the necessity to chain multiple of them, rather a single one each time (or a couple, but always specific and of a specific count, so I was able to hook them together without iterations and async/await), one of the use-cases finally necessitated chaining an unknown number of Tasks together.
How I deal with this currently
The way I am dealing with this currently is to append a call to Wait() inside the ContinueWith call, i.e.:
foreach (AsyncProcessor<T> processor in m_processors)
{
chainedTask = chainedTask.ContinueWith(t => processor.Process(input).Wait());
}
I would appreciate any idea on how I should do this, or how I could do it more elegantly (or, "async-properly", so to speak). Also, I would like to know how I can do this without async/await.
Why my question is different from this question, which did not answer my question entirely.
Because the linked question has two tasks, so the solution is to simply write the two lines required, while I have an arbitrary (and unknown) number of tasks, so I need an suitable iteration. Also, my method is not async. I now understand (from the single briefly available answer, which was deleted) that I could do it fairly easily if I changed my method to async and await each processor's Task method, but I still wish to know how this could be achieved without async/await syntax.
Why my question is not a duplicate of the other linked questions
Because none of them explains how to chain correctly using ContinueWith and I am interested in a solution that utilizes ContinueWith and does not make use of the async/await pattern. I know this pattern may be the preferable solution, I want to understand how to (if possible) make arbitrary chaining using ContinueWith calls properly. I now know I don't need ContinueWith. The question is, how do I do it with ContinueWith?
foreach + await will run Processes sequentially.
public async Task ProcessInputAsync(T input)
{
foreach (var processor in m_processors)
{
await processor.Process(input));
}
}
Btw. Process, should be called ProcessAsync
The method Task.ContinueWith does not understand async delegates, like Task.Run do, so when you return a Task it considers this as a normal return value and wraps it in another Task. So you end up receiving a Task<Task> instead of what you expected to get. The problem would be obvious if the AsyncProcessor.Process was returning a generic Task<T>. In this case you would get a compile error because of the illegal casting from Task<Task<T>> to Task<T>. In your case you cast from Task<Task> to Task, which is legal, since Task<TResult> derives from Task.
Solving the problem is easy. You just need to unwrap the Task<Task> to a simple Task, and there is a built-in method Unwrap that does exactly that.
There is another problem that you need to solve though. Currently your code suppresses all exceptions that may occur on each individual AsyncProcessor.Process, which I don't think it was intended. So you must decide which strategy to follow in this case. Are you going to propagate the first exception immediately, or you prefer to cache them all and propagate them at the end bundled in an AggregateException, like the Task.WhenAll does? The example bellow implements the first strategy.
public class CompositeAsyncProcessor<T>
{
//...
public Task Process(T input)
{
Task current = Task.CompletedTask;
foreach (AsyncProcessor<T> processor in m_processors)
{
current = current.ContinueWith(antecessor =>
{
if (antecessor.IsFaulted)
return Task.FromException<T>(antecessor.Exception.InnerException);
return processor.Process(input);
},
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default
).Unwrap();
}
return current;
}
}
I have used an overload of ContinueWith that allows configuring all the options, because the defaults are not ideal. The default TaskContinuationOptions is None. Configuring it to ExecuteSynchronously you minimize the thread switches, since each continuation will run in the same thread that completed the previous one.
The default task scheduler is TaskScheduler.Current. By specifying TaskScheduler.Default you make it explicit that you want the continuations to run in thread-pool threads (for some exceptional cases that won't be able to run synchronously). The TaskScheduler.Current is context specific, and if it ever surprises you it won't be in a good way.
As you see there are a lot of gotchas with the old-school ContinueWith approach. Using the modern await in a loop is a lot easier to implement, and a lot more difficult to get it wrong.

Task and Parallel.Invoke in a library, is it a bad idea to use it?

I have read that to do a fake async method in this way it is a bad idea:
public int myMethodSyn()
{
//sync operations
return result;
}
public async int myMethodAsync()
{
return await Task.Run(myMethodSync);
}
One of the reasons that I have read it is because for example, ASP can have scalability problems with this kind of libraries because tasks use the thread pool and ASP need the thread pool to attend each call. So the library can consume all the threads of the thread pool al block ASP. SO it is better allow to the client decides how to use the thread pool.
If am not wrong, Parallel.Invoke use the thread pool too to run methods in parallel, so I guess that if I use a method in my library that uses parallel.Invoke, or parallel.Foreach or any of this ways to run code in parallel, I would have the same problem. Is it true?
My idea is to run two mthods in parallel because they are indepent and I could get a better performance if I run them in parallel. So I would have somthing like that:
public int myMainMethodSync()
{
int result01 = myMethod01Sync();
int result02 = myMethod02Sync();
return result01 + result02;
}
private void myMethod01Sync()
{
}
private void myMethod02Sync()
{
}
public int myMainMethodAsync()
{
Task myTsk01 = Task.Run(myMethod01Sync);
Task myTsk02 = Task.Run(myMethod02Sync);
Task.WhenAll(myTsk01, myTsk02);
return myTsk01.Result + myTsk02.Result;
}
public int Task myMainMethodParallel()
{
int result01;
int result02;
Parallel.Invoke(() => result01 = myMethod01Sync(),
() => result02 = myMethod02Sync());
return result01 + result02;
}
The idea is it to have a sync method that run the two methods in sync. So the client who use the library knows that the method will not use thread pool.
Later I have two options to run the methods at the same time, with tasks or with parallel.Invoke.
In the case of the tasks, I am using a fake async methods because I am wraping the sync method inside a task, that use two threads from the threadpool. If I am not wrong, this is not recommended.
The other option it is to use Parallel.Invoke, that uses threads from thread pool too, so I guess it has the same problem that with tasks, so I guess that it is not recommended too.
In my case I would prefer to use task, because I can decide with a condition when to run the method02Sync for example, according to some condiciotion, so I could save the cost to assign a thread to run the second method if I know that it is not needed in some cases. I guess in parallel.Invoke this is not possible.
However, I think that in this case, how I implement a sync method too, I let the client to choose the method that it considerates better in its case, so really it is a bad option to use tasks in the async method?
If both solutions are bad, tasks and Parallel.Invloke, then it is not recommended to run parallel code in libraries and only use it in the top level, in the UI or client of the library? Because I guess that in this case the use of parallel is very restrictive, because in the top level, in the UI, it is not possible to use parallel if it decides it is possible because tell to library use threads or not, because it wouldn't have parallel methods.
In sumary, is my solution, expose sync and async methods a bad idea? is it bad idea to use task or parallel code in the libraries? If one of them it is better option, which one?
Thanks.
is my solution, expose sync and async methods a bad idea?
Let me reformulate the question to make it more general:
Is it a good idea to expose two versions of a method with different performance characteristics?
I think that most of the time, it is a bad idea. The API of your library should be clear, you should not make the users of your library constantly keep choosing between the two options. I think it's your responsibility as a library author to make the decision, even if it's going to be the wrong one for some of your users.
If the differences between the two options are dramatic, you could consider some approach that lets your users to choose between them. But I think having two separate methods is the wrong choice, something like an optional parameter would be a better approach, because it means there is a clear default.
The one exception I can think of is if the signatures of the two methods are different, like with truly async methods. But I don't think that applies to your use of Tasks to parallelize CPU-bound methods.
Is it bad idea to use task or parallel code in the libraries?
I think you should use them cautiously. You are right that your users might not be happy if your library uses more resources (here, threads) to make itself faster. On the other hand, most methods of parallelizing code are smart enough that if the amount of available thread pool threads is limited, they will still work fine. So, if you measured that the speedup gained by parallelizing your code is significant, I think it's okay to do it.
If one of them it is better option, which one?
I think this is more a matter of which one you prefer as a matter of code style. The performance characteristics of Parallel.Invoke() with two actions and synchronously waiting for two Tasks should be comparable.
Though keep in mind that your call to Task.WhenAll doesn't really do anything, since WhenAll returns a Task that completes when all its component Tasks complete. You could instead use Task.WaitAll, but I'm not sure what would be the point, since you're already implicitly waiting for both Tasks by acessing their Results.

Writing an asynchronous process that can be awaited

I have been researching how to convert my (synchronous) algorithms into asynchronous ones. (TAP)
First, just to be clear, this question is not about "what is Async and Await does" ( I already have read the excellent posts of Stephen Cleary , for example Async and Await (If anyone is interested read the link- it is very informative)
I have also read already the chapter on concurrency of "C# in a nutshell".
This question is not about how async functions use await to call functions either. I already know that.
Unfortunately in almost all the things I read, the await Task.Delay(10) is used to "make a asynchronous function". For example:
public async Task<int> GetResult()
{
int result= await GiveMeTheInt();
}
public async Task<int> GiveMeTheInt() //<--is async needed here? (oops! I just realize it is...
{
await Task.Delay(100);
return(10);
}
In this example for instance I already understand the magic of async await in the GetResult() function but the implementation of GiveMeTheInt() is not very useful.(They just put a Delay as a generic asynchronous function and leave it at that)
So my question is about the "GiveMeTheInt"-type of questions (not the ones who call them).
The question
If I have an algorithm written in a function that so far has been synchronous, how can I convert this to be used asynchronously?
This is not a duplicate question, the closest I have found is Turning a Syncronous method async in which the poster is told to use a async version of his method that already exists. In my case, this does not exist.
My algorithms consist mainly of Image processing so in essence scanning a large array and changing the values of each pixel. Something like
void DoSomethingToImage(int[,] Image)
{
for(int i=0;i<width;i++)
for(int j=0;j<height;j++)
{
Image[i,j]=255;
}
}
(This is a fictional example, the operation is different of course)
The closest I have gotten an answer to this is to put the function inside a Task.Run() but I am not sure if this is the way to do it.
Any help will be greatly appreciated
So take a look at your method:
void DoSomethingToImage(int[,] image)
{
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
image[i, j] = 255;
}
}
}
Is this asynchronous? Obviously not. This is just CPU-bound work that will keep the processor busy for a bit. As such, it is not a good candiate to make asynchronous on its own. It should be run synchronously.
What if you are consuming this from an asynchronous part of the application? You certainly don’t want the user interface to block because you are iterating through a lot of pixels. So the solution is to load the work off to another thread. You do that using Task.Run:
await Task.Run(() => DoSomethingToImage(image));
So you would write that whenever you call the DoSomethingToImage method from an asynchronous method. Now, if you only use that method inside asynchronous contexts, you could argue that it might make sense to move the Task.Run into the function:
Task DoSomethingToImageAsync(int[,] image)
{
return Task.Run(() => { … });
}
Is this a good idea? In general no, because now you are making the method look asynchronous when it’s in fact not. All it does is spawn a new thread that does the work, and then it waits for the thread to complete. So now you are hiding that part and also make a method doing highly synchronous work decide that a thread should be started. That’s rarely a good idea. And there is nothing wrong with keeping the method as it is, to show that it’s synchronous, and make the calling code responsible of deciding how that code should be run.
If I have an algorithm written in a function that so far has been synchronous, how can I convert this to be used asynchronously?
So, coming back to your actual question, this is actually difficult to answer. The answer is probably just this: “It depends”.
If a method does CPU-bound work, you’re better off keeping it synchronous and let calling code decide how to run it. If you are doing mostly I/O work where you interact with other interfaces (network, file system, etc.), then that’s a good candidate for making it asynchronous, especially considering that many of those interfaces will already offer asynchronous ways to communicate with them.
One final note regarding your “is async needed here?” question in your code: You need the async keyword whenever you want to use await inside of it. The mere presence of the async keyword does not make a method asynchronous though (not even the return type does indicate that).

When to use "async" instead of returning a new Task.Run task?

So here I have a function
static bool Login(SignupData sd)
{
bool success=false;
/*
Perform login-related actions here
*/
}
And there is another function
static Task<bool> LoginAsync(SignupData sd)
{
return Task.Run<bool>(()=>Login(sd));
}
Now, I've come across a rather different implementation of this pattern, where you would add the async keyword to a function which returns Task<TResult> (so that it ends up looking like: async Task<TResult> LoginAsync(SignupData sd)). In this case, even if you return TResult instead of a Task<TResult>, the program still compiles.
My question here is, which implementation should be prefered?
static Task<bool> LoginAsync(SignupData sd)
{
return Task.Run<bool>(()=>Login(sd));
}
OR this one?
async static Task<bool> LoginAsync(SignupData sd)
{
bool success=Login(sd);
return success;
}
You shouldn't be doing either. Asynchronous methods are useful if they can prevent threads from being blocked. In your case, your method doesn't avoid that, it always blocks a thread.
How to handle long blocking calls depends on the application. For UI applications, you want to use Task.Run to make sure you don't block the UI thread. For e.g. web applications, you don't want to use Task.Run, you want to just use the thread you've got already to prevent two threads from being used where one suffices.
Your asynchronous method cannot reliably know what works best for the caller, so shouldn't indicate through its API that it knows best. You should just have your synchronous method and let the caller decide.
That said, I would recommend looking for a way to create a LoginAsync implementation that's really asynchronous. If it loads data from a database, for instance, open the connection using OpenAsync, retrieve data using ExecuteReaderAsync. If it connects to a web service, connect using the asynchronous methods for whatever protocol you're using. If it logs in some other way, do whatever you need to make that asynchronous.
If you're taking that approach, the async and await keywords make perfect sense and can make such an implementation very easy to create.
While HVD is correct, I will dive into async in an attempt to describe its intended use.
The async keyword, and the accompanying await keyword is a shortcut method of implementing non blocking code patterns within your application. While it plays along perfectly with the rest of the Task Parallel Library (TPL), it isn't usually used quite the same. It's beauty is in the elegance of how the compiler weaves in the asynchronicity, and allows it to be handled without explicitly spinning off separate threads, which may or may not be what you want.
For Example, let's look at some code:
async static Task<bool> DoStuffAsync()
{
var otherAsyncResult = doOtherStuffAsync();
return await otherAsyncResult
}
See the await keyword? It says, return to the caller, continue on until we have the result you need. Don't block, don't use a new thread, but basically return with a promise of a result when ready (A Task). The calling code can then carry on and not worry about the result until later when we have it.
Usually this ends up requiring that your code becomes non-blocking the whole way down (async all the way as it were), and often this is a difficult transition to understand. However, if you can it is incredibly powerful.
The better way to handle your code would be to make the synchronous code call the async one, and wait on it. That way you would be async as much as possible. It is always best to force that level as high as possible in your application, all the way to the UI if possible.
Hope that made sense. The TPL is a huge topic, and Async/Await really adds some interesting ways of structuring your code.
https://msdn.microsoft.com/en-us/library/hh191443.aspx

C# Asynchronous Options for Processing a List

I am trying to better understand the Async and the Parallel options I have in C#. In the snippets below, I have included the 5 approaches I come across most. But I am not sure which to choose - or better yet, what criteria to consider when choosing:
Method 1: Task
(see http://msdn.microsoft.com/en-us/library/dd321439.aspx)
Calling StartNew is functionally equivalent to creating a Task using one of its constructors and then calling Start to schedule it for execution. However, unless creation and scheduling must be separated, StartNew is the recommended approach for both simplicity and performance.
TaskFactory's StartNew method should be the preferred mechanism for creating and scheduling computational tasks, but for scenarios where creation and scheduling must be separated, the constructors may be used, and the task's Start method may then be used to schedule the task for execution at a later time.
// using System.Threading.Tasks.Task.Factory
void Do_1()
{
var _List = GetList();
_List.ForEach(i => Task.Factory.StartNew(_ => { DoSomething(i); }));
}
Method 2: QueueUserWorkItem
(see http://msdn.microsoft.com/en-us/library/system.threading.threadpool.getmaxthreads.aspx)
You can queue as many thread pool requests as system memory allows. If there are more requests than thread pool threads, the additional requests remain queued until thread pool threads become available.
You can place data required by the queued method in the instance fields of the class in which the method is defined, or you can use the QueueUserWorkItem(WaitCallback, Object) overload that accepts an object containing the necessary data.
// using System.Threading.ThreadPool
void Do_2()
{
var _List = GetList();
var _Action = new WaitCallback((o) => { DoSomething(o); });
_List.ForEach(x => ThreadPool.QueueUserWorkItem(_Action));
}
Method 3: Parallel.Foreach
(see: http://msdn.microsoft.com/en-us/library/system.threading.tasks.parallel.foreach.aspx)
The Parallel class provides library-based data parallel replacements for common operations such as for loops, for each loops, and execution of a set of statements.
The body delegate is invoked once for each element in the source enumerable. It is provided with the current element as a parameter.
// using System.Threading.Tasks.Parallel
void Do_3()
{
var _List = GetList();
var _Action = new Action<object>((o) => { DoSomething(o); });
Parallel.ForEach(_List, _Action);
}
Method 4: IAsync.BeginInvoke
(see: http://msdn.microsoft.com/en-us/library/cc190824.aspx)
BeginInvoke is asynchronous; therefore, control returns immediately to the calling object after it is called.
// using IAsync.BeginInvoke()
void Do_4()
{
var _List = GetList();
var _Action = new Action<object>((o) => { DoSomething(o); });
_List.ForEach(x => _Action.BeginInvoke(x, null, null));
}
Method 5: BackgroundWorker
(see: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx)
To set up for a background operation, add an event handler for the DoWork event. Call your time-consuming operation in this event handler. To start the operation, call RunWorkerAsync. To receive notifications of progress updates, handle the ProgressChanged event. To receive a notification when the operation is completed, handle the RunWorkerCompleted event.
// using System.ComponentModel.BackgroundWorker
void Do_5()
{
var _List = GetList();
using (BackgroundWorker _Worker = new BackgroundWorker())
{
_Worker.DoWork += (s, arg) =>
{
arg.Result = arg.Argument;
DoSomething(arg.Argument);
};
_Worker.RunWorkerCompleted += (s, arg) =>
{
_List.Remove(arg.Result);
if (_List.Any())
_Worker.RunWorkerAsync(_List[0]);
};
if (_List.Any())
_Worker.RunWorkerAsync(_List[0]);
}
}
I suppose the obvious critieria would be:
Is any better than the other for performance?
Is any better than the other for error handling?
Is any better than the other for monitoring/feedback?
But, how do you choose?
Thanks in advance for your insights.
Going to take these in an arbitrary order:
BackgroundWorker (#5)
I like to use BackgroundWorker when I'm doing things with a UI. The advantage that it has is having the progress and completion events fire on the UI thread which means you don't get nasty exceptions when you try to change UI elements. It also has a nice built-in way of reporting progress. One disadvantage that this mode has is that if you have blocking calls (like web requests) in your work, you'll have a thread sitting around doing nothing while the work is happening. This is probably not a problem if you only think you'll have a handful of them though.
IAsyncResult/Begin/End (APM, #4)
This is a widespread and powerful but difficult model to use. Error handling is troublesome since you need to re-catch exceptions on the End call, and uncaught exceptions won't necessarily make it back to any relevant pieces of code that can handle it. This has the danger of permanently hanging requests in ASP.NET or just having errors mysteriously disappear in other applications. You also have to be vigilant about the CompletedSynchronously property. If you don't track and report this properly, the program can hang and leak resources. The flip side of this is that if you're running inside the context of another APM, you have to make sure that any async methods you call also report this value. That means doing another APM call or using a Task and casting it to an IAsyncResult to get at its CompletedSynchronously property.
There's also a lot of overhead in the signatures: You have to support an arbitrary object to pass through, make your own IAsyncResult implementation if you're writing an async method that supports polling and wait handles (even if you're only using the callback). By the way, you should only be using callback here. When you use the wait handle or poll IsCompleted, you're wasting a thread while the operation is pending.
Event-based Asynchronous Pattern (EAP)
One that was not on your list but I'll mention for the sake of completeness. It's a little bit friendlier than the APM. There are events instead of callbacks and there's less junk hanging onto the method signatures. Error handling is a little easier since it's saved and available in the callback rather than re-thrown. CompletedSynchronously is also not part of the API.
Tasks (#1)
Tasks are another friendly async API. Error handling is straightforward: the exception is always there for inspection on the callback and nobody cares about CompletedSynchronously. You can do dependencies and it's a great way to handle execution of multiple async tasks. You can even wrap APM or EAP (one type you missed) async methods in them. Another good thing about using tasks is your code doesn't care how the operation is implemented. It may block on a thread or be totally asynchronous but the consuming code doesn't care about this. You can also mix APM and EAP operations easily with Tasks.
Parallel.For methods (#3)
These are additional helpers on top of Tasks. They can do some of the work to create tasks for you and make your code more readable, if your async tasks are suited to run in a loop.
ThreadPool.QueueUserWorkItem (#2)
This is a low-level utility that's actually used by ASP.NET for all requests. It doesn't have any built-in error handling like tasks so you have to catch everything and pipe it back up to your app if you want to know about it. It's suitable for CPU-intensive work but you don't want to put any blocking calls on it, such as a synchronous web request. That's because as long as it runs, it's using up a thread.
async / await Keywords
New in .NET 4.5, these keywords let you write async code without explicit callbacks. You can await on a Task and any code below it will wait for that async operation to complete, without consuming a thread.
Your first, third and forth examples use the ThreadPool implicitly because by default Tasks are scheduled on the ThreadPool and the TPL extensions use the ThreadPool as well, the API simply hides some of the complexity see here and here. BackgroundWorkers are part of the ComponentModel namespace because they are meant for use in UI scenarios.
Reactive extensions is another upcoming library for handling asynchronous programming, especially when it comes to composition of asynchronous events and methods.
It's not native, however it's developed by Ms labs. It's available both for .NET 3.5 and .NET 4.0 and is essentially a collection of extension methods on the .NET 4.0 introduced IObservable<T> interface.
There are a lot of examples and tutorials on their main site, and I strongly recommend checking some of them out. The pattern might seem a bit odd at first (at least for .NET programmers), but well worth it, even if it's just grasping the new concept.
The real strength of reactive extensions (Rx.NET) is when you need to compose multiple asynchronous sources and events. All operators are designed with this in mind and handles the ugly parts of asynchrony for you.
Main site: http://msdn.microsoft.com/en-us/data/gg577609
Beginner's guide: http://msdn.microsoft.com/en-us/data/gg577611
Examples: http://rxwiki.wikidot.com/101samples
That said, the best async pattern probably depends on what situation you're in. Some are better (simpler) for simpler stuff and some are more extensible and easier to handle when it comes to more complex scenarios. I cannot speak for all the ones you're mentioning though.
The last one is the best for 2,3 at least. It has built-in methods/properties for this.
Other variants are almost the same, just different versions/convinient wrappers

Categories

Resources