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

时间:2015-11-26 14:54:37

标签: c# asynchronous

我有这个方法

public void Execute(Action action)
{
    try
    {
        action();
    }
    finally
    {
    }
}

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

public async Task ExecuteAsync(Action action)
{
    try
    {
        await action();
    }
    finally
    {
    }
}

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

  

等待'运算符只能在异步lambda中使用   表达。考虑使用' async'标记这个lambda表达式。   改性剂。

3 个答案:

答案 0 :(得分:21)

如果您想在代理上await,则必须是Func<Task>Func<Task<T>>类型。 Action等同于void Action()命名方法。您无法等待void,但您可以等待Task Func()Task<T> Func

public async Task ExecuteAsync(Func<Task> func)
{
    try
    {
        await func();
    }
    finally
    {
    }
}

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

答案 1 :(得分:4)

试试这个:

public async void ExecuteAsync(Action action)
{
    await Task.Run(action); 
}

使用Task.Run()通过在其他任务上运行您的操作来创建等待。 并且还要记住,处理“等待”的例外情况并不像intended那样有效。

更好地将action()调用试着在该包装上捕获一个do Task.Run()

答案 2 :(得分:0)

让我们将您的起点简化为:

public void Execute(Action action)
{
  action();
}

因为你说finally并不重要。

有效但毫无意义:

public async Task ExecuteAsync(Action action)
{
    action();
}

这与做的几乎相同:

public Task ExecuteAsync(Action action)
{
  action();
  return Task.FromResult(0);
}

也就是说,它会执行非异步执行的操作,然后返回“已完成”的任务,这样就无法获得任何内容。值得注意的是,从非异步转为异步通常是一个有效的分路点。

更好:

public async Task ExecuteAsync(Action action)
{
  await Task.Run(() => action()); 
}

在这种情况下,因为它是一个单独的返回空值的调用可以简化为:

public async Task ExecuteAsync(Action action)
{
  await Task.Run(action); 
}

这是否值得做是另一回事。这会释放当前线程,但会转移到另一个线程来完成工作。如果我们在调用时只是等待它的结果,那么我们也可以调用非异步版本并完成它。但是,如果我们在调用者中执行WaitAll,或者从中受益于此的其他内容,那么它确实可能有用。

可能会好得多:

public async Task ExecuteAsync(Action action)
{
  await actionAsync();
}

这里有我们正在调用的方法的Async版本,所以我们改为使用它。现在,如果actionAsync只是旋转一个线程或使用线程池,那么这可能与上面的相同。但是,如果actionAsync使用异步I / O执行某些操作,则可以获得更大的好处。

请注意,在这种情况下,我们可以直接调用我们得到的任务:

public Task ExecuteAsync(Action action)
{
  return actionAsync();
}

但是,如果我们需要在我们的方法中await之后完成某些操作,那就不一样了。 E.g:

public void Execute(Action action)
{
  action();
  otherAction();
}

必须成为:

public async Task Exectute(Action action)
{
  await actionAsync();
  await otherActionAsync();
}

或者如果otherAction没有异步版本:

public async Task Exectute(Action action)
{
  await actionAsync();
  otherAction();
}