问题
I have an async method with the following signature:
IAsyncResult BeginGetMyNumber(string foo, string bar, string bat, int bam, AsyncCallback callback, object state)
I want to execute it using Factory.FromAsync like this:
var result = Task<int>.Factory.FromAsync(
instance.BeginGetMyNumber,
instance.EndGetMyNumber,
"foo",
"bar",
"bat",
100, /*bam*/
null);
but I get the following error:
Argument 1: cannot convert from 'method group' to 'System.Func'
It seems there is no suitable overloaded FromAsync method http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.fromasync.aspx, it only supports up to 5 arguments (including callback and state) on the BeginXXX method.
Other than refactoring the BeginXXX method to take an object rather than six arguments, is there a way to execute it using FromAsync?
回答1:
result = Task<string>.Factory.FromAsync(
(callback, state) => instance.BeginGetMyNumber("foo", "bar", "bat", 1, callback, state),
instance.EndGetMyNumber, state: null);
This technique (partial function application) works for begin methods with any number of input params.
回答2:
Actually it seems I can use the overloaded method for Factory.FromAsync( that takes an IAsyncResult object as the first argument and a callback method as the second:
result = Task<string>.Factory.FromAsync(
instance.BeginGetMyNumber("foo", "bar", "bat", 1, null, null),
instance.EndGetMyNumber);
回答3:
Yeah, basically, you've run out of arguments. :(
The FromAsync
method only takes a maximum of three passed-to-the-async-call arguments, spelled out in full like so:
var result = Task<int>
.Factory
.FromAsync<string,string,string>(
BeginGetMyNumber,
EndGetMyNumber,
"foo",
"bar",
"bat",
null);
Which would work if you had:
IAsyncResult BeginGetMyNumber(
string foo,
string bar,
string bat,
AsyncCallback callback,
object state)
{
}
But ye've got one too many.
Ooh, got something that might help - you WILL want to clean this up, this is extremely thrown-together!!!
public static class Ext
{
public static Task<TResult> FromAsync<TArg1, TArg2, TArg3, TArg4, TResult>(
this TaskFactory<TResult> factory,
Func<TArg1,TArg2,TArg3,TArg4,AsyncCallback, object, IAsyncResult> beginMethod,
Func<IAsyncResult, TResult> endMethod,
TArg1 arg1,
TArg2 arg2,
TArg3 arg3,
TArg4 arg4,
object state,
TaskCreationOptions creationOptions = TaskCreationOptions.None,
TaskScheduler scheduler = null)
{
scheduler = scheduler ?? TaskScheduler.Current;
AsyncCallback callback = null;
if (beginMethod == null)
{
throw new ArgumentNullException("beginMethod");
}
if (endMethod == null)
{
throw new ArgumentNullException("endMethod");
}
TaskCompletionSource<TResult> tcs =
new TaskCompletionSource<TResult>(state, creationOptions);
try
{
if (callback == null)
{
callback = delegate (IAsyncResult iar)
{
tcs.TrySetResult(endMethod(iar));
};
}
beginMethod(arg1, arg2, arg3, arg4, callback, state);
}
catch
{
tcs.TrySetResult(default(TResult));
throw;
}
return tcs.Task;
}
}
来源:https://stackoverflow.com/questions/15582450/too-many-arguments-in-beginxxx-for-fromasync