Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Await alternative in .NET 4.0?

What would be the best alternative for the await keyword in .NET 4.0 ? I have a method which needs to return a value after an asynchronous operation. I noticed the wait() method blocks the thread completely thus rendering the asynchronous operation useless. What are my options to run the async operation while still freeing the UI thread ?

like image 720
Dante Avatar asked Nov 14 '12 11:11

Dante


People also ask

Is await necessary in C#?

If your controller or API method internally invoked asynchronous operations, await them. If it doesn't invoke any then it itself doesn't need to be async. *Note: A lot of times people will, often naively, not await an asynchronous operation because they want it to be "fire and forget".

Can we use async without await C#?

The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete.

Is await the same as synchronous?

Your async code block is waiting for the await call to return to continue, however the rest of your application isn't waiting and can still continue like normal. In contrast, a synchronous call would make your entire application or thread wait until the code finished executing to continue on with anything else.

Is await the same as task wait?

Wait and await - while similar conceptually - are actually completely different. Wait will synchronously block until the task completes. So the current thread is literally blocked waiting for the task to complete.


2 Answers

I think your basic options are

  • Using Task and .ContinueWith()
  • Using the Async CTP and async / await
  • Using Reactive Extensions

The easiest way is probably to install the Async CTP. As far as I know the license allows comercial usage. It patches the compiler and comes with a 150kb dll that you can include into your project.

You can use Task and .ContinueWith(). But that means, that you have to take some effort with exeption handling and flow control.

Tasks are a functional construct. That's why ContinueWith() does not mix well with imperative constructs like for loops or try-catch blocks. Therefore async and await got introduced, so that the compiler can help us out.

If you can't have that support of the compiler (i.e. you use .Net 4.0), your best bet is to use the TAP together with a functional framework. Reactive Extensions is a very good framework to treat asynchronous methods.

Just google for "reactive extensions tasks" to get started.

like image 132
PeterB Avatar answered Oct 05 '22 08:10

PeterB


You could implement a behaviour like await with the yield coroutines, i'm using this in non-4.5 code. You need a YieldInstruction class which is retrieved from the method which should run async:

public abstract class YieldInstruction
{
    public abstract Boolean IsFinished();
}

Then you need some implementations of the YieldInstruction ( a.e. TaskCoroutine which handles a task ) and use it this way ( Pseudo code ):

public IEnumerator<YieldInstruction> DoAsync()
{
    HttpClient client = ....;
    String result;
    yield return new TaskCoroutine(() => { result = client.DownloadAsync(); });
    // Process result here
}

Now you need a scheduler which handles the execution of the instructions.

for (Coroutine item in coroutines)  
{  
    if (item.CurrentInstruction.IsFinished())  
    {
         // Move to the next instruction and check if coroutine has been finished 
         if (item.MoveNext()) Remove(item);
    }
}

When developing WPF or WinForms applications you are also able to avoid any Invoke calls if you are updating the coroutines at the right time. You also might be able to extend the idea to make your life even easier. Sample:

public IEnumerator<YieldInstruction> DoAsync()
{
    HttpClient client = ....;
    client.DownloadAsync(..);

    String result;
    while (client.IsDownloading)
    {
        // Update the progress bar
        progressBar.Value = client.Progress;
        // Wait one update
        yield return YieldInstruction.WaitOneUpdate;
    }
    // Process result here
}
like image 28
Felix K. Avatar answered Oct 05 '22 09:10

Felix K.