Task.Factory.FromAsync和BeginX/EndX之间的区别?

Rya*_*hel 11 .net c# asynchronous task-parallel-library

当使用TcpClient中的标准BeginRead和EndRead方法并使用Task.Factory.FromAsync时,我有非常相似的代码.

以下是一些示例..错误处理代码未显示.

Task.Factory.FromAsync:

private void Read(State state)
{
    Task<int> read = Task<int>.Factory.FromAsync(state.Stream.BeginRead, state.Stream.EndRead, state.Bytes, state.BytesRead, state.Bytes.Length - state.BytesRead, state, TaskCreationOptions.AttachedToParent);

    read.ContinueWith(FinishRead);
}

private void FinishRead(Task<int> read)
{
    State state = (State)read.AsyncState;

    state.BytesRead += read.Result;
}
Run Code Online (Sandbox Code Playgroud)

使用BeginRead和EndRead标准使用回调:

private void Read(State state)
{
    client.BeginRead(state.Bytes, state.BytesRead, state.Bytes.Length - state.Bytes.Read, FinishRead, state);
}

private void FinishRead(IAsyncResult async)
{
    State state = (State)async.AsyncState;

    state.BytesRead += state.Stream.EndRead(async);
}
Run Code Online (Sandbox Code Playgroud)

这两个都很好,但我很好奇他们的差异.两者的代码行几乎相同,它们似乎都执行完全相同的功能并具有相同的效率.哪个更好?您更喜欢在生产代码中看到什么?

Jon*_*eet 14

我更愿意看到Task<T>基于代码:

  • 它更容易提供构图; 例如,编写一个接收Task<T>任务集合并返回另一个代表这些任务的多数裁决的任务的方法相当容易.同样,您可以等到任务集合中的任何一个完成,等等.
  • 它提供了更灵活的连续运行位置安排.
  • 它允许返回任务本身的类型安全性和比IAsyncResult返回的有点贫血类型更多的信息BeginRead.
  • 使用任务指定错误处理和取消比使用Begin/End模型更简单.
  • Task<T>使用async/await在C#5中获得更好的语言支持 - 如果你的代码库已经Task<T>普遍使用,那么利用它会容易

基本上在.NET 4上运行的现代代码中,Task<T>是表示正在进行的任务的惯用方法.与早期的尝试相比,这是一个更富裕的工作环境,如果你有机会,我会接受它.显然,如果您使用的是.NET 3.5或更早版本,生活会有点困难,但我假设您正在提出问题,这Task<T>是一个选择......

  • @RyanPeschel:是的,它不会阻止 - 否则它将毫无意义.不,你不需要相同的try/catch,因为你可以指定一个延迟来运行错误,另一个继续运行取消,另一个运行成功 - 看看ContinueWith的重载.您还可以*测试*任务的状态,而不仅仅是尝试获取结果(查看Task.Status).基本上,整个事情要丰富得多.C#5中的异步支持非常棒. (2认同)