Ho un codice che funziona esattamente come desiderato. Tuttavia, il nostro server di build aziendale rifiuta qualsiasi check-in che abbia un avviso del compilatore.Come convertire l'azione in Func <Task> senza eseguire l'attività?
Il seguente avviso è (come previsto) visualizzato per il costruttore Action con le conversioni di Action to Func, poiché non sto utilizzando un'attesa.
Questo metodo asincrono manca degli operatori di 'attesa' e verrà eseguito in modo sincrono. Prendi in considerazione l'utilizzo dell'operatore 'attendi' per attendere chiamate API non bloccanti o 'attendere Task.Run (...)' per eseguire il lavoro con CPU su un thread in background.
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)
{
//...
}
}
}
cosa è un modo corretto per riscrivere il codice in modo che l'azione sia correttamente convertito Funz senza essere eseguita ancora o creare un nuovo thread (cioè attendere Task.Run())?
Update - Risposta suggerita # 1
_operation =() => Nuova operazione (operation.Invoke);
_rollback =() => nuova attività (rollback.Invoke);
Ho provato prima. Fa sì che questo test unitario non ritorni mai.
[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);
}
Update - risposta accettata
private async Task ConvertToTask(Action action)
{
action.Invoke();
await Task.FromResult(true);
}
Ecco il costruttore d'azione aggiornato:
public TransactionOperation(Action operation, Action rollback)
{
_operation =() => ConvertToTask(operation);
_rollback =() => ConvertToTask(rollback);
Status = OperationStatus.NotStarted;
}
Perché sei fare async su una cosa che verrà eseguita in modo sincrono? –
Bene, 'async() => {operation.Invoke(); attendere Task.FromResult (0); } 'Dovrebbe farlo, ma il commento sopra è ancora pertinente: perché vuoi racchiudere il codice sincrono come asincrono, in primo luogo? – Noseratio