如何在不运行任务的情况下将Action转换为Func <task>?</task>

时间:2015-03-26 01:43:52

标签: c# asynchronous async-await

我的代码可以根据需要精确运行。但是,我们的公司构建服务器拒绝任何具有编译器警告的签入。

为Action构造函数显示以下警告(正如预期),其中包含Action to Func转换,因为我没有使用await语句。

  

这种异步方法缺乏等待&#39;运营商并将同步运行。考虑使用&#39; await&#39;运营商等待非阻塞API调用,或等待Task.Run(...)&#39;在后台线程上进行CPU绑定工作。

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正确转换为Func而不执行或创建新线程(即等待Task.Run())?


更新 - 建议的答案#1

  

_operation =()=&gt;新任务(operation.Invoke);

     

_rollback =()=&gt;新任务(rollback.Invoke);

我之前试过这个。它导致此单元测试永远不会返回。

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

2 个答案:

答案 0 :(得分:11)

您可以使用Task.FromResult(0)

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

答案 1 :(得分:2)

你的意思是这样的:

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

然后,函数将返回一个尚未启动的所需操作的任务。

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

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