如何在没有 运行 任务的情况下将 Action 转换为 Func<Task>?

How to convert Action to Func<Task> without running the Task?

我的代码完全符合要求。但是,我们的公司构建服务器拒绝任何具有编译器警告的签入。

由于我没有使用 await 语句,因此(如预期的那样)为具有 Action 到 Func 转换的 Action 构造函数显示以下警告。

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

public class TransactionOperation
{
    private readonly Func<Task> _operation;
    private readonly Func<Task> _rollback;

    public OperationStatus Status { get; private set; }

    public TransactionOperation(Func<Task> operation, Func<Task> rollback)
    {
        _operation = operation;
        _rollback = rollback;
        Status = OperationStatus.NotStarted;
    }

    public TransactionOperation(Action operation, Action rollback)
    {
        _operation = async () => operation.Invoke();
        _rollback = async () => rollback.Invoke();
        Status = OperationStatus.NotStarted;
    }

    public async Task Invoke()
    {
        try
        {
            Status = OperationStatus.InProcess;
            await _operation.Invoke();
            Status = OperationStatus.Completed;
        }
        catch (Exception ex)
        {
            //...
        }
    }
}

重写该代码的正确方法是什么,以便 Action 在尚未执行或创建新线程(即 await Task.Run())的情况下正确转换为 Func?


更新 - 建议的答案 #1

_operation = () => new Task(operation.Invoke);

_rollback = () => new Task(rollback.Invoke);

我以前试过这个。它导致此单元测试永远不会 return.

[TestMethod, TestCategory("Unit Test")]
public async Task Transaction_MultiStepTransactionExceptionOnFourthAction_CorrectActionsRolledBack()
{
    var operation = new TransactionOperation(PerformAction, () => RollbackOperation(1));
    var operation2 = new TransactionOperation(PerformAction, () => RollbackOperation(2));
    var operation3 = new TransactionOperation(PerformAction, () => RollbackOperation(3));
    var operation4 = new TransactionOperation(ExceptionAction, () => RollbackOperation(4));
    var operation5 = new TransactionOperation(PerformAction, () => RollbackOperation(5));
    var transaction = new Transaction(new[] { operation, operation2, operation3, operation4, operation5 });

    await IgnoreExceptions(transaction.ExecuteAsync);

    AssertActionsPerformedThrough(4);
    AssertActionsRolledBackThrough(4);
}

更新 - 已接受的答案

private async Task ConvertToTask(Action action)
{
    action.Invoke();
    await Task.FromResult(true);
}

这是更新后的 Action 构造函数:

public TransactionOperation(Action operation, Action rollback)
{
    _operation = () => ConvertToTask(operation);
    _rollback = () => ConvertToTask(rollback);
    Status = OperationStatus.NotStarted;
}

你的意思是这样的:

_operation = () => new Task(operation.Invoke);
_rollback = () => new Task(rollback.Invoke);

这些功能将 return 具有尚未启动的所需操作的任务。

我认为您需要将 Invoke 方法更新为以下内容以获得您正在寻找的行为:

Status = OperationStatus.InProcess;
await Task.Run(() =>
    {
        _operation().Start();
        _operation().Wait();
    });
Status = OperationStatus.Completed;

你可以直接使用 Task.FromResult(0):

_operation = async () => { operation.Invoke(); await Task.FromResult(0); };