Reputation: 23
I have the following code where the continuation code isn't getting executed.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Konsole
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Main starting...");
Task.Run(async () =>
{
await Job1();
})
.ContinueWith(async t =>
{
await Job2();
}).Wait();
Console.WriteLine("Main ending...");
}
public static async Task Job1()
{
await Task.Run(() =>
{
for (int i = 1; i <= 2; i++)
{
Thread.Sleep(1000);
Console.WriteLine($"Job1 {i}");
}
});
}
public static async Task Job2()
{
await Task.Run(() =>
{
for (int i = 1; i <= 2; i++)
{
Thread.Sleep(1000);
Console.WriteLine($"Job2 {i}");
}
});
}
}
}
Console output:
Main starting... Job1 1 Job1 2 Main ending...
I expected Job2 to be executed as well before the application closed.
Upvotes: 2
Views: 298
Reputation: 456747
You should not use ContinueWith
; it's a dangerous, low-level method. In this case, you're encountering a problem because ContinueWith
does not understand asynchronous delegates.
Ideally, you should replace all calls to ContinueWith
(and Wait
) with await
:
static async Task Main(string[] args)
{
Console.WriteLine("Main starting...");
await Task.Run(async () =>
{
await Job1();
});
await Job2();
Console.WriteLine("Main ending...");
}
If you break out the variables so you can see the types, it will become more clear why the original code wasn't working:
static async Task Main(string[] args)
{
Console.WriteLine("Main starting...");
Task runTask = Task.Run(async () =>
{
await Job1();
});
Task<Task> continuationTask = runTask.ContinueWith(async t =>
{
await Job2();
});
// continuationTask is a Task<Task>.
// This waits for the "outer" task only, not the "inner" task.
continuationTask.Wait();
Console.WriteLine("Main ending...");
}
Upvotes: 1
Reputation: 11464
To answer you question, you need to 'Unwrap' the task from the first async call as follows:
Task.Run(async () =>
{
await Job1();
})
.ContinueWith(async t =>
{
await Job2();
})
.Unwrap()
.Wait();
There are a number of other things to comment on here though.
If you are using async/await, you should really use it all the way through. Your question doesn't specify which version of c# you are using. If you are using C# 7.1 or above, you should make your main method an async method as follows:
public static async Task Main()
{
Console.WriteLine("Main starting...");
await Job1();
await Job2();
Console.WriteLine("Main ending...");
}
Also, as pointed out by @Sean, Thread.Sleep
is a bad idea in these scenarios, you should use await Task.Delay(1000);
instead.
Task.Delay Documentation
A great article with some async/await best practices can be found on MSDN as well.
Upvotes: 4