为什么TaskFactory.FromAsync()重载需要提供状态对象?

时间:2015-08-01 17:20:00

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

详见TPL and Traditional .NET Framework Asynchronous Programming MSDN文章和Stephen Toub的Tasks and the APM Pattern博客文章,TaskFactory.FromAsync()TaskFactory<TResult>.FromAsync()方法可用于调整Begin *( )和End *()API符合APM模式,用于任务并行库。

下面我将仅讨论TaskFactory<TResult>.FromAsync()重载,因为我的问题不依赖于符合APM的API是否会产生值。

有三个重载接受IAsyncResult对象,即:

  • FromAsync(IAsyncResult, Func<IAsyncResult, TResult>)
  • FromAsync(IAsyncResult, Func<IAsyncResult, TResult>, TaskCreationOptions)
  • FromAsync(IAsyncResult, Func<IAsyncResult, TResult>, TaskCreationOptions, TaskScheduler)

我知道这些API在Begin *()API方法除了AsyncCallback和状态object(例如Too many arguments in BeginXXX for FromAsync?)之外还有三个以上参数的情况下非常有用,或当Begin*() API未完全符合APM模式时,因为它不采用状态object参数(例如How can I use the AsyncCTP with an TFS APM Method (Query.Begin/EndQuery)?)。

我不明白为什么剩余的重载(例如FromAsync(Func<AsyncCallback, Object, IAsyncResult>, Func<IAsyncResult, TResult>, Object))都需要提供状态object。此状态object将传递给Begin*() API,但在APM模式中,状态object供调用方私人使用。因此,object通过Begin*() API传递状态FromAsync()并不重要。

上面链接的MSDN文章标题为&#34;提供自定义状态数据&#34;建议在延续委托中捕获任何所需的状态,并将状态对象的null传递给FromAsync()。但是,这并不能解释为什么FromAsync()方法需要给出状态对象。

为什么状态object在返回的Task<TResult>无法访问时需要传递?

1 个答案:

答案 0 :(得分:4)

好吧,如果你follow the source code,你可以看到确实可以使用Task var task = Task.Factory.FromAsync<TResult>(...); object state = task.AsyncState 实例访问状态Task.AsyncState

Task.Factory.StartNew

此属性同时保存异步操作的状态,如var task = Task.Factory.StartNew(_ => { }, "bar"); Console.WriteLine(task.AsyncState); // prints "bar"

null

因此,由于状态是可访问的,因此期望能够将状态作为参数传递,并使用状态参数将API加倍一次,并且一次不会听起来像是更好的选项。特别是当你可以传递os.system(''.join(["loimpress ",filename]))时。