0

I have an asynchronous task that is conditional. I want to await it if it's called, but, obviously, not wait for it if it's not.

This is what I tried.

Task l;

if(condition)
{
    l = MyProcessAsync();
}

//do other stuff here

if(condition)
{
    await Task.WhenAll(l); //unassigned variable error
}

I get Use of unassigned local variable 'l' compiler error.

What's the appropriate way to do this?

under
  • 2,519
  • 1
  • 21
  • 40
  • 4
    `Task l = null;` or `Task l = Task.CompletedTask;` – Guru Stron Sep 03 '20 at 11:15
  • 1
    Thanks! Why not put it as the answer? – under Sep 03 '20 at 11:23
  • Didn't have time to add some description ATM =) – Guru Stron Sep 03 '20 at 12:08
  • 2
    Note: you need to be *really really careful* with this approach; this is inherently concurrent; if `MyProcessAsync` is **completely unrelated** to anything in "do other stuff here", then you might get away with it, but this is the equivalent to starting a worker thread for half the code: if it touches any of the same objects, there could be major problems – Marc Gravell Sep 03 '20 at 12:28

2 Answers2

6

In your example, you have not assigned to Task l;.

You need to at least assign it to null.

Here is a working sample in a console application:

    static async Task Main(string[] args)
    {
        var condition = true;
        Task task = null;

        if (condition)
        {
            task = MyProcessAsync();
        }

        Console.WriteLine("Do other stuff");

        if (task != null)
        {
            await task;
        }

        Console.WriteLine("Finished");
        Console.ReadLine();
    }

    static async Task MyProcessAsync()
    {
        await Task.Delay(2000);
        Console.WriteLine("After async process");
    }

Outputs:

Do other stuff
After async process
Finished

ndogac
  • 1,185
  • 6
  • 15
DGrowns
  • 406
  • 2
  • 8
2

As far as I know C# does not analyze if conditions in if statement are the same. Next code will work cause actually there will not be any branching at all generated by compiler:

Task l;
if (1==1) // or  if(true)
{
    l = Task.CompletedTask;
}
//do other stuff here
if (1==1) // or  if(true)
{
    await Task.WhenAll(l); //unassigned variable error
} 

So in you code you need to initialize local variable, cause using an unassigned local has high likelihood of being a bug (also see this section of specification), so you need to initialize it for example to null or Task.CompletedTaskfrom the get-go:

Task l = null; // or Task l = Task.CompletedTask;
Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • I like the idea of initializing it to `Task.CompletedTask` more than `null`. I think if we use `Task.CompletedTask` as default value we could even just await `l` without a huge performance penalty. – Ackdari Sep 04 '20 at 11:52