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

use*_*441 9 c# asynchronous .net-4.0 task-parallel-library async-await

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

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

Moo*_*ght 10

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

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

所以,一个例子可能是

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

使用该方法并附加使用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);
}
Run Code Online (Sandbox Code Playgroud)

或者一气呵成

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);
Run Code Online (Sandbox Code Playgroud)

您还可以手动实现TAP模式,以便更好地控制实现.自己实现TAP,您创建一个TaskCompletionSource<TResult>对象,执行异步操作,并在结束时,调用SetResult,SetExceptionSetCanceled方法,或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;
}
Run Code Online (Sandbox Code Playgroud)

消费TaskCompleationSource从消费者.

我希望这有帮助.


L.B*_*L.B 8

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

ContinueWithTaskScheduler.FromCurrentSynchronizationContext

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

这大致相当于

var str = await SomeFuncAsync() //returning "test";
this.textBox1.Text = str;
Run Code Online (Sandbox Code Playgroud)


nos*_*tio 5

是否可以在没有关键字await或async的情况下在.NET 4.0中使用基于任务的异步模式(TAP)?我问是因为我们陷入了C#4)

一种值得注意且方便的技巧是使用yieldIEnumerable<Task>。例如,摘自Stephen Toub的“带有任务的异步操作的处理序列”

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”));
Run Code Online (Sandbox Code Playgroud)

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

  • 这是一种很好的做事方式,与async / await思维方式并不需要多大的偏离(除了略有不同的异常处理,您不能在try主体内使用yield)。捕捉块)。在简单的场景中,延续和延续链没有错,但是当您需要丰富的异步任务组合并且不能使用`async / await`时,这绝对是正确的方法。+1 (2认同)

Adi*_*dil 0

如果没有 async/await 关键字,您将无法利用编译器提供的便利性来使用新模式。但是,您可以使用.NET 4 框架中的任务并行库 (TPL)来利用基于任务的并行性