C# Task.Factory.fromsync和BeginX/EndX之间的区别是什么?
在使用TcpClient中的标准BeginRead和EndRead方法以及Task.Factory.FromAsync时,我有非常相似的代码 这里有一些例子。。未显示错误处理代码 Task.Factory.fromsync:C# Task.Factory.fromsync和BeginX/EndX之间的区别是什么?,c#,.net,asynchronous,task-parallel-library,C#,.net,Asynchronous,Task Parallel Library,在使用TcpClient中的标准BeginRead和EndRead方法以及Task.Factory.FromAsync时,我有非常相似的代码 这里有一些例子。。未显示错误处理代码 Task.Factory.fromsync: private void Read(State state) { Task<int> read = Task<int>.Factory.FromAsync(state.Stream.BeginRead, state.Stream.EndRea
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;
}
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);
}
这两种方法都很好,但我对它们的不同之处感到好奇。两者的代码行几乎相当,它们似乎都执行完全相同的功能,并且具有相同的效率。哪一个更好?您希望在生产代码中看到什么?我更希望看到基于任务的代码:
- 它使构图更容易;例如,编写一个方法相当容易,该方法接受一组
任务,并返回另一个代表这些任务大多数的任务。同样地,您可以等到任务集合中的任何一个任务完成,等等任务
- 它提供了更灵活的延续运行位置调度
- 它允许任务本身以类型安全的方式返回,并且比
返回的有点贫乏的BeginRead
类型返回的信息多得多IAsyncResult
- 使用任务指定错误处理和取消比使用开始/结束模型更简单
使用async/await在C#5中获得了更好的语言支持-如果您的代码库已经普遍使用了Task
,那么利用这一点就会容易得多Task
基本上,在.NET4上运行的现代代码中,
Task
是表示正在进行的任务的惯用方式。这是一个比以前更丰富的工作环境,如果你有机会,我会欣然接受。显然,如果您使用的是.NET 3.5或更早版本,生活会有点困难,但我假设在您提问时,任务是一个选项…谢谢您的回答!不过我还是有点困惑。我知道BeginRead非常有效,因为回调使用IO完成端口,而不是阻塞。ContineRead在效率方面是否与EndRead相同,因为它不阻塞并且只在EndRead运行的同一时间运行?另外,您能否详细说明它如何支持更好的错误处理?我是否也必须在每个代码示例的state.BytesRead+=
行上执行相同的try-catch操作?@RyanPeschel:是的,它不会阻塞-否则它将毫无意义。不,您不需要相同的try/catch,因为您可以指定一个continuation在出错时运行,另一个在取消时运行,另一个在成功时运行-请查看continuateWith的重载。您还可以测试任务的状态,而不只是尝试获取结果(查看task.Status)。基本上,这一切都要丰富得多。C#5中的异步支持非常棒。我正在检查重载,但我不太明白您的意思。当出现错误/取消时,如何指定要运行的方法?我想我可能已经找到了。。你会用不同的函数多次调用ContinueWith吗?第二个参数类似于TaskContinuationOptions。如果你想在出现错误时运行所述方法,则只调用onfaulted
。@RyanPeschel:我在电话上无法详细说明,但请看TaskContinuationOptions。编辑:刚刚看到你的编辑;是的,这就是我说的。请注意,可以附加多个连续体。