2014-07-01 52 views
9

有没有使用.NET 4.0 Task-based Asynchronous Pattern (TAP)没有awaitasync关键字的方法吗? (我问,因为我们卡在C#4.0。)基于任务的使用异步模式(TAP)与.NET 4.0和C#4.0

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

+1

只是为了确保您不会错过任何东西,不要混淆.net和c#版本号:您可以编译使用'await/async'到.NET 4.0程序集的C#5代码。您只需引用异步定位包(它位于nuget)以使其正常运行。如果由于某种原因你被C#4编译器困住了,那么请看你的问题的答案,这是肯定的。 – jods

回答

0

没有异步/等待关键字,您将无法利用编译器提供的易用性来使用新模式。但是,您可以利用任务型并行使用Task Parallel Library (TPL) in .NET 4 framework

+0

请说明投票的理由。如果我错了,我可以继续删除我的答案... – Adil

+1

我已经改变了downvote。现在答案是正确的。如果你使用TPL来“手动”实现TAP,那么当代表的异步操作通过“Continuations”完成时,你必须完成结果任务,这就是所有正在做的事情...... – MoonKnight

+0

@Killercam是的,它有点儿误导......更新了答案。 – Adil

7

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

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

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

  1. 返回'热'(运行)TaskTask<TResult>
  2. 有'异步'后缀(例如SomeMethodAsync(...))。
  3. 重载以接受取消标记。
  4. 快速返回给调用者(初始化阶段很小)。
  5. 如果I/O绑定,不会绑定线程。

所以,一个例子可能是

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

使用方法和安装它使用UI同步上下文延续。

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,请创建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; 
} 

从消费者处消费TaskCompleationSource

我希望这会有所帮助。

0

是的。在我看来,用于“开始/结束”方法的异步包装器;

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

+0

非常感谢你分享好文章@serbasi –

4

是否有.NET使用基于任务的异步模式(TAP)的方式 4.0不包含此关键字等待或异步?我问,因为我们被困在C#4)

一个显着的和方便的黑客是使用yieldIEnumerable<Task>。例如,从斯蒂芬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伪同步线性码流。

+2

这是一种很好的做事方式,它不需要太偏离'async/await'思维方式(略有不同的异常处理 - 你不能在try-catch块的内部使用'yield')。简单场景中的延续和延续链没有什么问题,但是当你需要丰富的异步任务组合并且不能使用'async/await'时,这绝对是一条可行的路。 +1 –