Why can not catch this Exception? [duplicate] - c#

I am using a library which provides methods ending with ...Async and return Task. I am going to use these in a command line application. So I need to call them synchronously a lot.
C# of course does not allow calling these methods in Main method since you cannot use async modifier on Main method. Assume this is the task:
var task = datastore.Save(data);
I found several solutions like:
Tasks.WaitAll(task);
task.Wait();
however all these wrap thrown exceptions in AggregateException, I don't want that. I just want to say task.Result and I expect the original exception to be thrown.
When I use a method returning Task<TResult>, task.Result throws AggregateException even though there are no continuation tasks set. Why is this hapening?
I also have tried,
task.RunSynchronously();
it gives error:
RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method.
so I guess that's not for methods marked as async.
Any ideas on patterns using libraries designed for async apps in console apps where there is no asynchronous context?

I am going to use these in a command line application. So I need to call them synchronously a lot.
No, you don't. You can use async-await in a console application, you just need to make an async to sync transition at the very top. And you can do that by using Wait():
public static void Main()
{
MainAsync().Wait();
}
public static async Task MainAsync()
{
var datastore = …;
await datastore.SaveAsync();
}
Usually, combining await with Wait() is a bad idea (it can cause deadlocks), but it's the right solution here.
Note that if SaveAsync() throws an exception and you don't catch it, it will be rethrown as AggregateException from the Wait(). But you can catch it as the original exception in MainAsync() (because it doesn't use Wait()).
If you really wanted to get the first exception thrown directly, you could do something similar to what await does: task.GetAwaiter().GetResult(). Note that if the Task contains more than one exception, you will get only the first one (but the same applies to await).
Since C# 7.1, you can make your Main method async and the compiler will write the transition code for you:
public static async Task Main()
{
var datastore = …;
await datastore.SaveAsync();
}
When I use a method returning Task<TResult>, task.Result throws AggregateException even though there are no continuation tasks set. Why is this happening?
This has nothing to do with continuations. A single Task can represent multiple operations, and each of them can throw an exception. Because of that, Task methods always throw the exceptions wrapped in an AggregateException.
I also have tried task.RunSynchronously()
That doesn't make any sense. RunSynchronously() can only be used on Tasks that were created using the Task constructor. That's not the case here, so you can't use it. Tasks returned from async methods are always already started.

You can create a dummy Main
public static void Main()
{
MainAsync().Wait();
}
public static async Task MainAsync()
{
try {
var result = await dataStore.Save(data);
} catch(ExceptionYouWantToCatch e) {
// handle it
}
}
Also, see this answer: https://stackoverflow.com/a/9212343/1529246

As of C# 7.1 you can now declare the Main method as async. Just have to make sure your language is either set to default major version (which should work in VS 2019 now) or you can always target a specific version of the language.
See this link for details. Turn on async main

Related

Ignore an exception in an async method

I am coding an app (.Net 5) that needs to execute a few async methods. First it creates a Job, then it creates a Task within the job, then waits for the Task to complete, and finally deletes the Job. For context, these are Azure Batch Jobs and Tasks, but I only mention it to indicate that what I call a Task is not the .Net framework Task, but a plain class that just happens to be named that. Other than that, the fact that this is Azure Batch related makes no difference.
I have coded this method to do those steps:
private async Task ExecuteTask(string jobName, string taskName, CloudTask task)
{
string poolName = ConfigurationManager.AppSettings["PoolName"];
await taskScheduler.QueueBatchJob(poolName, jobName);
await taskScheduler.QueueBatchTask(jobName, task);
taskScheduler.WaitForTaskToComplete(jobName, taskName);
_ = this.taskScheduler.DeleteJob(jobName); // I am intentionally not awaiting here
}
The calling method has a try / catch, with extra code that may take a while to execute.
I am intentionally not awaiting the DeleteJob method as I don't need for that to be done in order to continue, and I also don't care if it fails. It's there for cleanup but there may later be another process to do proper cleanup.
Now, my question is, what happens if there actually is an error on that method? will it get catch by the parent try/catch if the parent method did not complete? I definitely do not want that so if that is the case, how can I ignore it?
I'll simply answer this question with some quotes from here:
Async void methods have different error-handling semantics. When an
exception is thrown out of an async Task or async Task method, that
exception is captured and placed on the Task object. With async void
methods, there is no Task object, so any exceptions thrown out of an
async void method will be raised directly on the
SynchronizationContext that was active when the async void method
started.
later in the same article
When you await a Task, the first exception is re-thrown, so you can catch the specific exception type (such as InvalidOperationException).
That basically means:
The Task returned by the method will contain the Exception but it will only be raised if you await it. Therefore not awaiting a Task results in all Exceptions being swallowed by the Task object.

How to call an async function in .NET without waiting for it [duplicate]

This question already has answers here:
How to safely call an async method in C# without await
(13 answers)
Closed 3 years ago.
I have an async function in C# as follows:
private static async Task AddEmoji(string emoji)
{
...
}
I have a situation where I'd like to call it but I don't want to wait for its result and I don't care if it works or not. What's the right way to go about this? I thought I could just call it without adding the async parameter:
AddEmoji("🏆");
... which works, but VS gives me a CS4014 compile warning, so I guess that's not right. I then tried to create a Task for it:
Task.Run(() => await AddEmoji("🏆"));
But that gives me an actual compile error:
Error CS4034 The 'await' operator can only be used within an async
lambda expression. Consider marking this lambda expression with the
'async' modifier.
What's the right way to go about this?
In your Task.Run(), the await doesn't go inside the Func<>. You would normally await on the Task itself (put the await before the Task.Run()), but I think in your case, you can omit the await in order to not wait and ignore the results:
Task.Run(() => AddEmjoi("🏆"))
I don't want to wait for its result and I don't care if it works or not.
This is extremely unusual; the first thing to check is this assumption, that you literally don't need to know when it completes (or if it completes), and that you're OK with silently ignoring all exceptions. This also means that when your app exits, you're OK with this work never getting done (and again, you won't know because exceptions are ignored) - bearing in mind that in hosted scenarios like ASP.NET, you don't control when your app exits.
That said, you can do "fire and forget" as such:
var _ = AddEmoji("🏆");
This does not apply to asp.net -- async void methods are not permitted in asp.net applications. Console, WPF, Winforms, etc, applications are fine however. See the comments for the full discussion.
The best thing to do is to await it inside an async void method.
The problem with just writing AddEmoji("🏆");, is: what happens if it fails? If an exception is thrown inside AddEmoji, then that exception is bundled up inside the Task which AddEmoji returned. However, because you threw that Task away, you'd never know. So AddEmoji can fail in a bad way, but you'd never know. This is why the compiler is giving you an error.
However, async void methods avoid that. If an exception is thrown inside an async void method, then that exception is re-thrown on the ThreadPool, which will bring down your application. You'll definitely know that something went wrong!
People advise against using async void methods, but they are perfect for fire-and-forget situations. The advice stems from people trying to use async void methods when they do want to know when the operation completed.
public async void AddEmojiImpl(string emoji) => await AddEmoji(emoji);
Or
public async void AddEmojiImpl(string emoji)
{
try
{
await AddEmojiImpl(emoji);
}
catch (EmojiAddException e)
{
// ...
}
}
Local functions are particularly useful for this.

Is it just plain wrong to return Task instead of Task<T>?

The task API feels sort of like a pit of failure, given how every possible thing I could do with it comes with more DON'T than DO. But I'm trying to use it more, and I'm confused about the entire issue of async void.
My problem happens in a place where my application's used a local data file forever, and because it was fast synchronous calls were used. Now some remote sources are an option, and they have enough latency I'm switching it all to be asynchronous.
So I've got a method that maybe looks like this:
void InitializeData() {
SomeProperty = _dataSource.Load(...);
}
The naive thing I want to do for low-friction is:
Task InitializeDataAsync() {
return Task.Run(() => {
SomeProperty = _dataSource.Load(...);
});
}
But there are SO many articles about how terrible it is to use async void, and they seem to blur with discussion of returning a Task. So is my best option really to write it like:
Task<DataType> FetchDataAsync() {
return _dataSource.LoadAsync(...);
}
...then hunt down all the callers and make them comply?
I feel like the argument people make is that async void is bad because of the different behavior of async Task and the dreaded UnobservedTaskException when you use await. In this situation, I'm very unlikely to ever be using await. Or if I do use await, it's always going to have a try/catch around it because we're already paranoid about UnobservedTaskException.
So:
Is "Don't use async void" the same thing as "Don't use Task?
If you don't use await, does it mitigate that?
If you do use await, does always wrapping it with a try/catch mitigate the issue?
async void is not the same as returning a Task. The problem with async void is there is no way to observe task exceptions (other then the global exception handler), and no way to wait for the task to complete (you actually can't await an async void method because there is nothing to await), this is why it should be avoided.
Returning Task does not have these problems, if you await it you know when it completes and you will get exceptions where you await so returning a Task is perfectly acceptable.
It looks like you're just confused. The await/async API is incredibly simple. The only confusing part is understanding the difference between await/async API and the Task API. I won't go into great detail about this as the Stephen Cleary's blog clearly covers this, but here is the important excerpt:
To reiterate a sentence from my last post, use Task.Run to call CPU-bound methods (from GUI threads). Do not use it just to “provide something awaitable for my async method to use”.
next...
The naive thing I want to do for low-friction is:
Task InitializeDataAsync() {
return Task.Run(() => {
SomeProperty = _dataSource.Load(...);
});
}
This is a clear case of offloading Sync code into a Async wrapper which doesn't really do any good.
But there are SO many articles about how terrible it is to use async void,
This is clearly not a async void method. This is a non-async Task returning method. Here is an async void method:
async void InitializeDataAsync() {
await Task.Run(() => {
SomeProperty = _dataSource.Load(...);
});
}
they seem to blur with discussion of returning a Task.
I've not read anything that blurs this information. It's pretty simple; if you have an async method, always return Task or Task<T> (except as stated below). The difference between using these two (Task or Task<T>) is purely design/architecture.
So is my best option really to write it like:
Best is really an opinion here. Both of these work and don't forget async/wait
async Task<DataType> FetchDataAsync() {
return await _dataSource.LoadAsync(...);
}
async Task FetchDataAsync() {
_data = await _dataSource.LoadAsync(...);
}
I feel like the argument people make is that async void is bad because of the different behavior of async Task and the dreaded UnobservedTaskException when you use await.
The most important difference is how exceptions are handled:
Excerpt:
Async void methods have different error-handling semantics. When an exception is thrown out of an async Task or async Task method, that exception is captured and placed on the Task object. With async void methods, there is no Task object, so any exceptions thrown out of an async void method will be raised directly on the SynchronizationContext that was active when the async void method started.
So
Or if I do use await, it's always going to have a try/catch around it because we're already paranoid about UnobservedTaskException.
This means that you can't catch an exception by try/catch around async void. That is a huge problem!
Is "Don't use async void" the same thing as "Don't use Task?"
Well this is apples and oranges. Yes: don't use async void unless you're using them for async event handlers.
Don't use Task's unless they are CPU bound or you're using a Framework call (or you've correctly wrapped your own method which uses IO Completion Ports).
If you don't use await, does it mitigate that?
Hopefully by now you understand that await/async is different from a Task, and what you're trying to do is write all await/async code.
If you do use await, does always wrapping it with a try/catch mitigate the issue?
Depends, as stated above.

Why doesn't this exception get thrown?

I use a set of tasks at times, and in order to make sure they are all awaited I use this approach:
public async Task ReleaseAsync(params Task[] TaskArray)
{
var tasks = new HashSet<Task>(TaskArray);
while (tasks.Any()) tasks.Remove(await Task.WhenAny(tasks));
}
and then call it like this:
await ReleaseAsync(task1, task2, task3);
//or
await ReleaseAsync(tasks.ToArray());
However, recently I have been noticing some strange behavior and set to see if there was a problem with the ReleaseAsync method. I managed to narrow it down to this simple demo, it runs in linqpad if you include System.Threading.Tasks. It will also work slightly modified in a console app or in an asp.net mvc controller.
async void Main()
{
Task[] TaskArray = new Task[]{run()};
var tasks = new HashSet<Task>(TaskArray);
while (tasks.Any<Task>()) tasks.Remove(await Task.WhenAny(tasks));
}
public async Task<int> run()
{
return await Task.Run(() => {
Console.WriteLine("started");
throw new Exception("broke");
Console.WriteLine("complete");
return 5;
});
}
What I don't understand is why the Exception never shows up anywhere. I would have figured that if the Tasks with the exception were awaited, it would throw. I was able to confirm this by replacing the while loop with a simple for each like this:
foreach( var task in TaskArray )
{
await task;//this will throw the exception properly
}
My question is, why doesn't the shown example throw the exception properly (it never shows up anywhere).
TL;DR: run() throws the exception, but you're awaiting WhenAny(), which doesn't throw an exception itself.
The MSDN documentation for WhenAny states:
The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state.
Essentially what is happening is that the task returned by WhenAny simply swallows the faulted task. It only cares about the fact that the task is finished, not that it has successfully completed. When you await the task, it simply completes without error, because it is the internal task that has faulted, and not the one you're awaiting.
A Task not being awaited or not using its Wait() or Result() method, will swallow the exception by default. This behavior can be modified back to the way it was done in .NET 4.0 by crashing the running process once the Task was GC'd. You can set it in your app.config as follows:
<configuration>
<runtime>
<ThrowUnobservedTaskExceptions enabled="true"/>
</runtime>
</configuration>
A quote from this blog post by the Parallel Programming team in Microsoft:
Those of you familiar with Tasks in .NET 4 will know that the TPL has the notion of “unobserved” exceptions. This is a compromise between two competing design goals in TPL: to support marshaling unhandled exceptions from the asynchronous operation to the code that consumes its completion/output, and to follow standard .NET exception escalation policies for exceptions not handled by the application’s code. Ever since .NET 2.0, exceptions that go unhandled on newly created threads, in ThreadPool work items, and the like all result in the default exception escalation behavior, which is for the process to crash. This is typically desirable, as exceptions indicate something has gone wrong, and crashing helps developers to immediately identify that the application has entered an unreliable state. Ideally, tasks would follow this same behavior. However, tasks are used to represent asynchronous operations with which code later joins, and if those asynchronous operations incur exceptions, those exceptions should be marshaled over to where the joining code is running and consuming the results of the asynchronous operation. That inherently means that TPL needs to backstop these exceptions and hold on to them until such time that they can be thrown again when the consuming code accesses the task. Since that prevents the default escalation policy, .NET 4 applied the notion of “unobserved” exceptions to complement the notion of “unhandled” exceptions. An “unobserved” exception is one that’s stored into the task but then never looked at in any way by the consuming code. There are many ways of observing the exception, including Wait()’ing on the Task, accessing a Task’s Result, looking at the Task’s Exception property, and so on. If code never observes a Task’s exception, then when the Task goes away, the TaskScheduler.UnobservedTaskException gets raised, giving the application one more opportunity to “observe” the exception. And if the exception still remains unobserved, the exception escalation policy is then enabled by the exception going unhandled on the finalizer thread.
From the comment:
these [tasks] were tied to managed resources and I wanted to release them when
they became available instead of waiting for all of them to complete
and then releasing.
Using a helper async void method may give you the desired behavior for both removing the finished tasks from the list and immediately throwing unobserved exceptions:
public static class TaskExt
{
public static async void Observe<TResult>(Task<TResult> task)
{
await task;
}
public static async Task<TResult> WithObservation(Task<TResult> task)
{
try
{
return await task;
}
catch (Exception ex)
{
// Handle ex
// ...
// Or, observe and re-throw
task.Observe(); // do this if you want to throw immediately
throw;
}
}
}
Then your code might look like this (untested):
async void Main()
{
Task[] TaskArray = new Task[] { run().WithObservation() };
var tasks = new HashSet<Task>(TaskArray);
while (tasks.Any<Task>()) tasks.Remove(await Task.WhenAny(tasks));
}
.Observe() will re-throw the task's exception immediately "out-of-band", using SynchronizationContext.Post if the calling thread has a synchronization context, or using ThreadPool.QueueUserWorkItem otherwise. You can handle such "out-of-band" exceptions with AppDomain.CurrentDomain.UnhandledException).
I described this in more details here:
TAP global exception handler

Cleanest way of dealing with an IAsyncOperationWithProgress?

I've been using C# for quite a while, but somehow have not yet had the pleasure of using the whole await/async thing new in .Net 4. Well, now I'm making a console application that links to the WinRT libraries and WinRT is really.. well, asynchronous.
One thing I'm needing to do right now is install a package. So, I use PackageManager.AddPackageAsync This is of course asynchonous and returns an IAsyncOperationWithProgress
I know I could do something like
bool Done=false;
void Foo()
{
var tmp=new PackageManager.AddPackageAsync(...);
tmp.Completed= ... FooBar;
while(!Done){}
}
void FooBar(...)
{
Done=true;
}
But I'm pretty sure the whole async and await thing was designed for exactly this scenario. However, I don't understand how to use it in this context on an IAsyncOperationWithProgress
.Net includes a GetAwaiter() extension method that makes IAsyncOperationWithProgress awaitable.
You can just write await tmp; in an async method.
Your async method will return a Task (or Task<T>), which you can await from another async method, or call Wait() to synchronously block.
Async and Await allows you to program an Async operation as if it occurs on the calling thread. First you have to declare your operation as being async then you await the async operation from the other guy. Finally you do whatever work you wanted to do after that operation is complete.
async void Foo()
{
var tmp=await new PackageManager().AddPackageAsync(...);
//do something else;
}
Calling Foo will make it run in the background, but when AddPackageAsync completes, Foo rejoins the calling thread (e.g. the UI thread) to complete its work.
The other option is to call GetAwaiter extension method and call Wait() on it to manually block until the operation completes.
You can subscribe to that progress by using an overload of AsTask method, like the following
...= await new PackageManager().AddPackageAsync(...).AsTask(new Progress<DeploymentProgress>(...));

Categories

Resources