简体   繁体   中英

Use Task-based Asynchronous Pattern (TAP) with .NET 4.0 and C# 4.0

Is there a way to use the Task-based Asynchronous Pattern (TAP) in .NET 4.0 without the await and async keywords? (I ask because we are stuck in C# 4.0.)

Also, is there an example of using TAP with WCF with .NET 4.0?

Yes you can. The TAP is just a sensible formalization of best practice when working with asynchronous code. Basically a TAP method

  1. Returns a 'hot' (running) Task or Task<TResult> .
  2. Has an 'Async' suffix (eg SomeMethodAsync(...) ).
  3. Is overloaded to accept a cancellation token.
  4. Returns quickly to the caller (with small initialisation phase).
  5. Does not tie up a thread if I/O bound.

So, an example might be

private Task SomeMethodAsync(CancellationToken token)
{
    return Task.Factory.StartNew(() => 
    {
        // Do something...
    }, token);
}

use the method and attach continuation which uses the UI synchronization context.

private void SomeOtherMethod()
{
    var tokenSource = new CancellationTokenSource();
    CancellationToken token = tokenSource.Token;
    TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext()

    // Options 1.
    Task t = SomeMethodAsync(token);
    Task c = t.ContinueWith(ant => 
        { 
            /* Do something and check exceptions */
        }, CancellationToken.None,
           TaskContinuationOptions.None, 
           scheduler);

    // Options 2.
    SomeMethodAsync(token).ContinueWith(ant => 
        { 
            /* Do something and check exceptions */
        }, CancellationToken.None,
           TaskContinuationOptions.None, 
           scheduler);
}

Or do it all in one go

Task t = Task.Factory.StartNew(() => 
    {
        /* Do Something */
    }, token).ContinueWith(ant => 
        { 
            /* Do something on UI thread after task has completed and check exceptions */
        }, CancellationToken.None,
           TaskContinuationOptions.None, 
           scheduler);

You can also implement the TAP pattern manually for better control over implementation. To implement the TAP yourself, you create a TaskCompletionSource<TResult> object, perform the asynchronous operation, and when it completes, call the SetResult , SetException , or SetCanceled method, or the Try version of one of these methods. When you implement a TAP method manually, you must complete the resulting task when the represented asynchronous operation completes. For example:

public static Task<int> ReadTask(this Stream stream, 
    byte[] buffer, int offset, int count, object state)
{
    var tcs = new TaskCompletionSource<int>();
    stream.BeginRead(buffer, offset, count, ar =>
    {
        try { tcs.SetResult(stream.EndRead(ar)); }
        catch (Exception exc) { tcs.SetException(exc); }
    }, state);
    return tcs.Task;
}

Consume the TaskCompleationSource from the consumer.

I hope this helps.

You don't need async/await. The keywords can be

ContinueWith and TaskScheduler.FromCurrentSynchronizationContext

Task.Factory.StartNew(() => { return "test"; } )
            .ContinueWith(task => { this.textBox1.Text = task.Result; },
                            CancellationToken.None,
                            TaskContinuationOptions.None, 
                            TaskScheduler.FromCurrentSynchronizationContext());

This is roughly equal to

var str = await SomeFuncAsync() //returning "test";
this.textBox1.Text = str;

Is there a way to use Task-based Asynchronous Pattern (TAP) in .NET 4.0 without the keyword await or async? I ask because we are stuck in C#4)

One notable and handy hack is to use yield and IEnumerable<Task> . Eg, from Stephen Toub's "Processing Sequences of Asynchronous Operations with Tasks" :

IEnumerable<Task> DoExample(string input) 
{ 
    var aResult = DoAAsync(input); 
    yield return aResult; 
    var bResult = DoBAsync(aResult.Result); 
    yield return bResult; 
    var cResult = DoCAsync(bResult.Result); 
    yield return cResult; 
    … 
}

… 
Task t = Iterate(DoExample(“42”));

This way, you can have a pseudo-synchronous linear code flow similar to async/await .

Without the async/await keywords you won't be able to utilize the easiness provided by compiler to use the new pattern. However you can leverage Task based parallelism using Task Parallel Library (TPL) in .NET 4 framework

yeah there is. Async Wrappers for "Begin/End" methods comes to my mind;

public static Task<WebResponse> GetResponseAsync(this WebRequest client)
{
return Task<WebResponse>.Factory.FromAsync(client.BeginGetResponse,
client.EndGetResponse, null);
}

i guess what you are looking for Implement a WCF Asynchronous Service Operation with Task

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM