将Action方法调用转换为异步Action方法调用

vcR*_*obe 19 c# asynchronous

我有这个方法

public void Execute(Action action)
{
    try
    {
        action();
    }
    finally
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

我需要将它转换为像这样的异步方法调用

public async Task ExecuteAsync(Action action)
{
    try
    {
        await action();
    }
    finally
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

上面代码的问题是编译器发出以下错误

'await'运算符只能在异步lambda表达式中使用.考虑使用'async'修饰符标记此lambda表达式.

Yuv*_*kov 27

如果你想要await代表,它必须是类型Func<Task>或Func<Task<T>>.An Action等同于void Action()命名方法.你不能等待void,但你可以等待Task Func()或Task<T> Func:

public async Task ExecuteAsync(Func<Task> func)
{
    try
    {
        await func();
    }
    finally
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

如果无法做到这一点,则意味着内部方法并非真正异步,而您实际想要做的是在线程池线程上执行同步委托,这是另一回事,并不是真的异步执行某些事情.在这种情况下,使用包装调用Task.Run就足够了.

  • 是的还有人混淆的是c#编译器允许`async()=> {await ...}`的类型为`Action`或`Func <Task>`.如果人们选择使用`Action`键入它,那么他们很难"等待"它.如果他们明智地选择使用`Func <Task>,那么它现在是等待的.这是使用`Func <Task>`而不是`Action`等方面的好事之一.我真的不喜欢编译器允许`Action`在这种情况下是清晰度的类型. (4认同)

Tam*_*nut 5

尝试这个:

public async void ExecuteAsync(Action action)
{
    await Task.Run(action); 
}
Run Code Online (Sandbox Code Playgroud)

通过Task.Run()在其他任务上运行操作,使用可以创建一个等待的对象。还要记住,处理“ awaitables”上的异常无法按预期工作。

最好将该action()调用包装起来,尝试Task.Run()在该包装上捕获一个do 。

  • 我认为应该避免Task.Run(),因为它将始终在单独的线程中运行。这就是为什么我尝试使用异步/等待的原因。 (2认同)