在.NET 4.0和C#4.0中使用基于任务的异步模式(TAP)

时间:2014-07-01 21:19:39

标签: c# asynchronous .net-4.0 async-await task-parallel-library

有没有办法在没有 awaitasync关键字的情况下使用.NET 4.0 中的Task-based Asynchronous Pattern (TAP)? (我问,因为我们陷入了C#4.0。)

此外,是否有使用TAP和WCF与.NET 4.0的示例?

5 个答案:

答案 0 :(得分:10)

是的,你可以。在使用异步代码时,TAP只是最佳实践的合理形式化。基本上是TAP方法

  1. 返回热门&#39; (正在运行)TaskTask<TResult>
  2. 有一个&#39; Async&#39;后缀(例如SomeMethodAsync(...))。
  3. 重载以接受取消令牌。
  4. 快速返回调用者(初始化阶段较小)。
  5. 如果I / O绑定,则不会占用线程。
  6. 所以,一个例子可能是

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

    使用该方法并附加使用UI同步上下文的continuation。

    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);
    }
    

    或者一气呵成

    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);
    

    您还可以手动实施TAP模式,以便更好地控制实施。要自己实现TAP,您需要创建一个TaskCompletionSource<TResult>对象,执行异步操作,完成后,调用SetResultSetExceptionSetCanceled方法,或者其中一种方法的Try版本。手动实现TAP方法时,必须在表示的异步操作完成时完成生成的任务。例如:

    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;
    }
    

    从消费者那里消费TaskCompleationSource

    我希望这会有所帮助。

答案 1 :(得分:8)

您不需要异步/等待。关键字可以是

ContinueWithTaskScheduler.FromCurrentSynchronizationContext

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

这大致等于

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

答案 2 :(得分:5)

  

有没有办法在.NET中使用基于任务的异步模式(TAP)   4.0没有关键字await或async?我问,因为我们陷入了C#4)

一个值得注意的方便的方法是使用yieldIEnumerable<Task>。例如,来自Stephen Toub的"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”));

这样,您可以使用类似于async/await的伪同步线性代码流。

答案 3 :(得分:0)

如果没有async / await关键字,您将无法利用编译器提供的简便性来使用新模式。但是,您可以使用Task Parallel Library (TPL) in .NET 4 framework

来利用基于任务的并行性

答案 4 :(得分:0)

是的,有。 Async Wrappers用于&#34;开始/结束&#34;我想到了一些方法;

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

我猜你在寻找 Implement a WCF Asynchronous Service Operation with Task