Reputation: 548
I have the following code for sample console application, but the method specified in Task continuation using TaskContinuationOptions.OnlyOnFaulted
never gets called.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Sample
{
class Program
{
public static void Main(string[] args)
{
int index = 0;
var cts = new CancellationTokenSource();
Task.Factory.StartNew(() => NewTask(index), cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default)
.ContinueWith(HandleException, cts.Token, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
// Some code
// ...
Console.ReadLine();
}
private static async Task NewTask(int index)
{
Console.WriteLine(index);
await Wait();
}
private static async Task Wait()
{
await Task.Delay(500);
throw new Exception("Testing 123");
}
private static void HandleException(Task task)
{
if (task != null && task.Exception != null)
{
var exceptions = task.Exception.Flatten().InnerExceptions;
if (exceptions != null)
foreach (var exception in exceptions)
Console.WriteLine(exception.Message);
}
}
}
}
Here, when an exception is thrown from Wait()
method, instead of HandleException(...)
being called, either program crashes or debugger shows an unhandled exception dialog box.
EDITED: Return type of NewTask
method is Task
.
Upvotes: 1
Views: 1459
Reputation: 457057
I have the following code for sample console application
I assume you're doing this to learn async
and await
. Here's some tips.
Task.Factory.StartNew
. Most of the time you don't need to execute code on a background thread, but if you do, then use Task.Run
.ContinueWith
. Use await
instead.For Console apps, just write a Main
like this:
public static void Main(string[] args)
{
MainAsync().Wait();
}
And then put your real logic into a real async
method:
public static async Task MainAsync()
{
...
}
You may find my async
intro helpful.
Upvotes: 3
Reputation: 185683
By calling Factory.StartNew
, you're actually creating a task whose method body just initiates your actual task, but your actual task has no continuation on it; only the outer, superfluous task (which won't throw an exception) has one.
Additionally, your async function is async void
. This makes it impossible to add a continuation. I'm going to go one step further and say that you should never, ever, make a function that's async void
. It should always be async Task
.
If you make that syntax change, your calling syntax is actually simpler:
NewTask(index).ContinueWith(HandleException, cts.Token,
TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
However, bear in mind that cancellation is not something that you get for free; you either need to be passing your token along to other asynchronous tasks that make use of it or you need to be checking it youself (or call .ThrowIfCancellationRequested()
).
As an aside, by convention any function which returns a Task
or Task<T>
should have its name end with Async
(i.e. it should be named NewTaskAsync
).
Upvotes: 4