Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

303
Vistas
Avoid checking condition twice when assigning from task awaited with Task.WhenAll()

Is there a better way to write this asynchronous code (e.g. so that I don't need to repeat if (myCondition) twice)? I want to avoid using Task.Run here.

var tasks = new List<Task>();
Task<String> t1 = null;
Task<String> t2 = null;

if (myCondition) {
    t1 = getAsync();
    tasks.Add(t1);
}

if (myOtherCondition) {
    t2 = getAsync2();
    tasks.Add(t2);
}

await Task.WhenAll(tasks)

if (myCondition) {
    result.foo = await t1;
}

if (myOtherCondition) {
    result.bar = await t2;
}
over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Without really knowing what your conditions are checking, I think I would usually move that check to within the method that actually relates to getting foo or bar. It seems like a case of your one method doing more than it's supposed to.

A different approach:

var fooTask = GetFoo();
var barTask = GetBar();

await Task.WhenAll(new [] { fooTask, barTask });
result.foo = (await fooTask) ?? result.foo;
result.bar = (await barTask) ?? result.bar;

// ...
async Task<string> GetFoo()
{
    if (!myCondition) {
        return Task.FromResult((string)null);
    }
    return await DoHeavyWorkFoo();
}

async Task<string> GetBar()
{
    if (!myOtherCondition) {
        return Task.FromResult((string)null);
    }
    return await DoHeavyWorkBar();
}
over 4 years ago · Santiago Trujillo Denunciar

0

One way to do this is to have two lists, one list of tasks and one list of actions. The actions will be invoked sequentially after the completions of all tasks, and will assign the properties of the result object. Example:

var tasks = new List<Task>();
var actions = new List<Action>();
var result = new MyClass();

if (myCondition)
{
    var task = getAsync();
    tasks.Add(task);
    actions.Add(() => result.Foo = task.Result);
}

if (myOtherCondition)
{
    var task = getAsync2();
    tasks.Add(task);
    actions.Add(() => result.Bar = task.Result);
}

await Task.WhenAll(tasks);

actions.ForEach(action => action());

This way you don't need to store each Task in a separate variable, because each lambda expression captures the task variable in the inner scope of the if block. When the Action is invoked, the task will be completed, and so the task.Result will not block.


Just for fun: If you want to get fancy, you could encapsulate this "parallel object initialization" functionality in an ObjectInitializer class, that would invoke all the asynchronous methods concurrently, and then create a new object and assign the value of each of its properties sequentially:

public class ObjectInitializer<TObject> where TObject : new()
{
    private readonly List<Func<object, Task<Action<TObject>>>> _functions = new();

    public void Add<TProperty>(Func<object, Task<TProperty>> valueGetter,
        Action<TObject, TProperty> propertySetter)
    {
        _functions.Add(async arg =>
        {
            TProperty value = await valueGetter(arg);
            return instance => propertySetter(instance, value);
        });
    }

    public async Task<TObject> Run(object arg = null)
    {
        var getterTasks = _functions.Select(f => f(arg));
        Action<TObject>[] setters = await Task.WhenAll(getterTasks);
        TObject instance = new();
        Array.ForEach(setters, f => f(instance));
        return instance;
    }
}

Usage example:

var initializer = new ObjectInitializer<MyClass>();
if (myFooCondition) initializer.Add(_ => GetFooAsync(), (x, v) => x.Foo = v);
if (myBarCondition) initializer.Add(_ => GetBarAsync(), (x, v) => x.Bar = v);
MyClass result = await initializer.Run();
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda