为什么 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,即:
FromAsync(IAsyncResult, Func<IAsyncResult, TResult>)
FromAsync(IAsyncResult, Func<IAsyncResult, TResult>, TaskCreationOptions)
FromAsync(IAsyncResult, Func<IAsyncResult, TResult>, TaskCreationOptions, TaskScheduler)
我知道这些 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
.
时
如 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,即:
FromAsync(IAsyncResult, Func<IAsyncResult, TResult>)
FromAsync(IAsyncResult, Func<IAsyncResult, TResult>, TaskCreationOptions)
FromAsync(IAsyncResult, Func<IAsyncResult, TResult>, TaskCreationOptions, TaskScheduler)
我知道这些 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
.