BeginXXX中的FromAsync参数太多了?

时间:2013-03-23 01:42:14

标签: c# asynchronous iasyncresult

我有一个带有以下签名的异步方法:

IAsyncResult BeginGetMyNumber(string foo, string bar, string bat, int bam, AsyncCallback callback, object state)

我想使用Factory.FromAsync执行它,如下所示:

var result  = Task<int>.Factory.FromAsync(
                instance.BeginGetMyNumber, 
                instance.EndGetMyNumber, 
                "foo",
                "bar",
                "bat",
                100, /*bam*/
                null);

但是我收到以下错误:

  

参数1:无法从&#39;方法组转换&#39;至   &#39; System.Func&#39;

似乎没有合适的重载FromAsync方法http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.fromasync.aspx,它只支持BeginXXX方法中最多5个参数(包括回调和状态)。

除了重构BeginXXX方法以获取对象而不是六个参数之外,有没有办法使用FromAsync执行它?

3 个答案:

答案 0 :(得分:8)

result = Task<string>.Factory.FromAsync(
  (callback, state) => instance.BeginGetMyNumber("foo", "bar", "bat", 1, callback, state),
   instance.EndGetMyNumber);

此技术(部分函数应用程序)适用于具有任意数量输入参数的begin方法。

答案 1 :(得分:7)

实际上我似乎可以使用Factory.FromAsync的重载方法(它将IAsyncResult对象作为第一个参数,将回调方法作为第二个参数:

result = Task<string>.Factory.FromAsync(
                instance.BeginGetMyNumber("foo", "bar", "bat", 1, null, null),
                instance.EndGetMyNumber);

答案 2 :(得分:5)

是的,基本上,你已经没有参数了。 :(

FromAsync方法最多只需要三个传递给异步调用的参数,完全拼写如下:

var result  = Task<int>
    .Factory
    .FromAsync<string,string,string>(
        BeginGetMyNumber,
        EndGetMyNumber,
        "foo",
        "bar",
        "bat",
        null);

如果你有:

,那将会奏效
IAsyncResult BeginGetMyNumber(
   string foo, 
   string bar, 
   string bat, 
   AsyncCallback callback, 
   object state)
{
}

但是你有太多了。

哦,得到的东西可能会有所帮助 - 你会想要清理它,这是非常混乱的!

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;
    } 
}