C# 将异步操作转换为异步函数委托,保留同步异常传递

C# 将异步操作转换为异步函数委托,保留同步异常传递,c#,.net,asynchronous,async-await,task,C#,.net,Asynchronous,Async Await,Task,我想将异步操作委托转换为返回指定值的异步函数委托。我提出了一种扩展方法: public static Func<Task<TResult>> Return<TResult>(this Func<Task> asyncAction, TResult result) { ArgumentValidate.NotNull(asyncAction, nameof(asyncAction)); return async () =>

我想将异步操作委托转换为返回指定值的异步函数委托。我提出了一种扩展方法:

public static Func<Task<TResult>> Return<TResult>(this Func<Task> asyncAction, TResult result)
{
    ArgumentValidate.NotNull(asyncAction, nameof(asyncAction));

    return async () =>
    {
        await asyncAction();
        return result;
    };
}
测试:

Func asyncAction=()=>writealByteAsync(null,null);
var asyncFunc=asyncAction.Return(42);
var task=asyncFunc();//ArgumentNullException应该在这里抛出
等待任务;//而是被扔到这里

好吧,您将无法在初始调用中使用
async
。这一点很清楚。但您可以使用同步委托调用函数,然后捕获返回的任务,在异步委托中等待它:

public static Func<Task<TResult>> Return<TResult>(this Func<Task> asyncAction, TResult result)
{
    ArgumentValidate.NotNull(asyncAction, nameof(asyncAction));

    return () =>
    {
        // Call this synchronously
        var task = asyncAction();
        // Now create an async delegate for the rest
        Func<Task<TResult>> intermediate = async () => 
        {
            await task;
            return result;
        };
        return intermediate();
    };
}
public static Func Return(此Func异步操作,TResult结果)
{
ArgumentValidate.NotNull(asyncAction,nameof(asyncAction));
return()=>
{
//同步调用此函数
var task=asyncAction();
//现在为其余部分创建一个异步委托
Func intermediate=async()=>
{
等待任务;
返回结果;
};
返回中间值();
};
}
或者,将其重构为两个方法,基本上将异步lambda表达式提取为异步方法:

public static Func<Task<TResult>> Return<TResult>(
    this Func<Task> asyncAction, TResult result)
{
    ArgumentValidate.NotNull(asyncAction, nameof(asyncAction));

    return () =>
    {
        var task = asyncAction();
        return AwaitAndReturn(task, result);
    };
}

public static async Func<Task<TResult>> AwaitAndReturn<TResult>(
    this Task asyncAction, TResult result)
{
    await task;
    return result;
}
公共静态函数返回(
此函数(异步操作,TResult结果)
{
ArgumentValidate.NotNull(asyncAction,nameof(asyncAction));
return()=>
{
var task=asyncAction();
返回等待和返回(任务、结果);
};
}
公共静态异步函数(
此任务(异步操作,TResult结果)
{
等待任务;
返回结果;
}

您能提供一个更具体的例子吗?不清楚为什么希望同步抛出异常。如果调用
asyncAction()
,也不会引发异常-它将返回一个出错的任务。@JonSkeet:你说得对;我的示例中有一个小错误(匿名函数不应该被标记为
async
)。这个问题现在有意义了吗?@Douglas:嗯。只是因为你的
Func
实际上没有做任何异步的事情。通常情况下,可能是代码实际使用了async/await,只是碰巧抛出了一个异常?在这一点上,您将再次调用
asyncAction()
而不是抛出。@DanielA.White:要了解如何使用它的具体示例,请查看的最后一个代码段(在“更新”下)中的第三个重载。
Func<Task> asyncAction = () => WriteAllBytesAsync(null, null);
var asyncFunc = asyncAction.Return(42);
var task = asyncFunc();   // ArgumentNullException should be thrown here
await task;               // but instead gets thrown here
public static Func<Task<TResult>> Return<TResult>(this Func<Task> asyncAction, TResult result)
{
    ArgumentValidate.NotNull(asyncAction, nameof(asyncAction));

    return () =>
    {
        // Call this synchronously
        var task = asyncAction();
        // Now create an async delegate for the rest
        Func<Task<TResult>> intermediate = async () => 
        {
            await task;
            return result;
        };
        return intermediate();
    };
}
public static Func<Task<TResult>> Return<TResult>(
    this Func<Task> asyncAction, TResult result)
{
    ArgumentValidate.NotNull(asyncAction, nameof(asyncAction));

    return () =>
    {
        var task = asyncAction();
        return AwaitAndReturn(task, result);
    };
}

public static async Func<Task<TResult>> AwaitAndReturn<TResult>(
    this Task asyncAction, TResult result)
{
    await task;
    return result;
}