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

Why do TaskFactory.FromAsync() overloads require a state object to be supplied?

TPL and Traditional .NET Framework Asynchronous Programming MSDN article and Stephen Toub's Tasks and the APM Pattern blog post, the TaskFactory.FromAsync() and TaskFactory<TResult>.FromAsync() 方法中所述,可用于调整 Begin*() 和 End*() APIs 以符合 APM 模式以与任务并行库一起使用。

下面我将只讨论 TaskFactory<TResult>.FromAsync() 重载,因为我的问题不取决于 APM-conforming API 是否产生一个值。

有三个重载接受IAsyncResult object,即:

我知道这些 API 在 Begin*() API 方法除了 AsyncCallback 和状态 [=20] 之外还需要三个以上参数的情况下很有用=](例如 Too many arguments in BeginXXX for FromAsync?), or when the Begin*() API does not fully conform to the APM pattern because it does not take a state object parameter (e.g. 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 供调用者私人使用。因此,FromAsync().

将什么状态 object 传递给 Begin*() API 并不重要

上面链接的 MSDN 文章有一个标题为 "Providing Custom State Data" 的部分,它建议在延续委托中捕获任何所需的状态,并将状态 object 的 null 传递给 FromAsync() .但是,这并不能解释为什么 FromAsync() 方法需要给出状态 object。

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

好吧,如果你 follow the source code you can see that the state can indeed be accessed from the Task instance using the (not so surprisingly named) Task.AsyncState:

var task = Task.Factory.FromAsync<TResult>(...);
object state = task.AsyncState

这个属性在其他情况下也保存异步操作的状态,比如Task.Factory.StartNew:

var task = Task.Factory.StartNew(_ => { }, "bar");
Console.WriteLine(task.AsyncState); // prints "bar"

因此,由于状态是可访问的,因此预计能够将状态作为参数传递,并且将 API 加倍一次,一次使用状态参数,一次不使用状态参数,这听起来不是更好的选择.特别是当你可以传入 null.