c# - net - Qual è il modo migliore per avvolgere un codice sincrono come un'attività asincrona?



vb net await task (1)

Sto implementando un metodo di interfaccia che è asincrono (restituisce Attività). Tuttavia, la mia implementazione è per necessità sincrona. Qual'è il miglior modo per farlo? C'è un modo integrato per farlo? Qui ci sono diverse opzioni che sto considerando:

  • Opzione 1: Task.FromResult

    return Task.FromResult(ComputeResult());

Questo è buono perché il mio codice viene eseguito in modo sincrono. Lo svantaggio è che se ComputeResult () fallisce o viene annullato, il mio metodo gira invece di restituire un'attività fallita.

  • Opzione 2: Task.Run

    return Task.Run(() => ComputeResult());

Ciò propaga il fallimento e la cancellazione in modo più naturale. Tuttavia, questo introduce anche un thread-hop non necessario.

  • Opzione 3: TaskCompletionSource

    var tcs = new TaskCompletionSource<T>();
    try 
    { 
        tcs.SetResult(ComputeResult()); 
    }
    catch (OperationCanceledException) 
    { 
        tcs.SetCanceled(); 
    }
    catch (Exception ex) 
    { 
        tcs.SetException(ex); 
    }
    
    return tcs.Task;

Questo fa propagare il fallimento / cancellazione ed evita il thread-hop, ma è più prolisso e complesso.


Altre due opzioni che potresti aver trascurato:

  • basta rendere il metodo async e return ComputeResult() . Sopprimere l'avvertenza del compilatore con pragma . Se non ti piace sopprimere l'avviso, puoi farlo:

    async Task<Result> ComputeResultAsync()
    {
        await Task.FromResult(0);
        return ComputeResult();
    }
  • utilizzare Task.RunSynchronously :

    Task<Result> ComputeResultAsync()
    {
        var task = new Task<Result>(() => ComputeResult());
        task.RunSynchronously(TaskScheduler.Default);
        return task;
    }

Quest'ultimo fornirà propagazione delle eccezioni simile al metodo async . Notare tuttavia, in determinate condizioni (come quando è troppo profondo nello stack), RunSynchronously potrebbe comunque essere eseguito in modo asincrono.





task