如何在没有 运行 任务的情况下将 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); };
我的代码完全符合要求。但是,我们的公司构建服务器拒绝任何具有编译器警告的签入。
由于我没有使用 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); };