As far as I know, it's not good practice to use them when there's application specific error handling available.
I'm calling a method from a WCF service like so:
Service.Login += new EventHandler<LoginCompletedEventArgs>(LoginCompleted);
Service.LoginAsync(username, password);
In the resulting 'LoginCompleted' method I can use the following to check for errors:
if (e.Error == null)
As errors can be analysed once the method has completed, is it still necessary to place try-catch blocks around the 'LoginAsync' call? In other words, can anything go wrong with the 'LoginAsync' call?
Yes. Things can go wrong with the call itself... for example, say your network goes down and you can't actually complete the call. The try/catch would be useful for those situations. Handling the exceptions that occurred during the asynchronous operation is being done exactly how you should be doing it.
Basically, if you want to handle any exceptions in making the call, use the try/catch. If you want to handle any exceptions during the asynchronous operation, use the e.Error as you have been.
Not quite sure what could happen, but some scenarios jump to my head: out threads in the pool, out of memory...I would think that it is not necessary.
Related
In my ASP.NET Core app I have few (dozen) methods created in the form of
public async Task DoStuff()
{
// ...
}
So, no return type.
Later, I realized that I accidentally forgot to include await on such methods here and there, in the caller methods (which were obviously left without async keyword as async "zombie virus" hasn't spread out that far yet).
During the execution, there were no unwanted consequences whatsoever.
The thing is, Visual Studio generates no warning message either when such thing happens and I'm asking myself, is there actually any danger present of lefting out the await in such cases? I know that await should be applied on every async method naturally, but I don't really understand the reasons behind this when caller practically has no return value to use. Perhaps something with catching exceptions?
I haven't found any clear answer to this for the general statement is 'simply include await'. And believe it or not, this async/await thing, to which I'm relatively new, keeps biting me repeatedly from time to time.
During the execution, there were no unwanted consequences whatsoever.
I disagree. The resulting code is dangerous. ASP.NET pre-Core was able to detect similar situations and throw an exception ("An asynchronous module or handler completed while an asynchronous operation was still pending"). For technical reasons, ASP.NET Core cannot detect this situation so you don't get that "safety net" exception, but the situation itself is still just as bad.
The thing is, Visual Studio generates no warning message either when such thing happens
You don't get CS4014 ("Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the await operator to the result of the call.")?
is there actually any danger present of lefting out the await in such cases? I know that await should be applied on every async method naturally, but I don't really understand the reasons behind this when caller practically has no return value to use. Perhaps something with catching exceptions?
Yes, there are dangers. Task (even without a result type) is used for two things: for the caller to know when the operation completes, and for the caller to detect exceptions from that operation.
So, the one issue is that exceptions are silently swallowed. More specifically, exceptions from the async method are captured by the async state machine and placed on the returned Task, which is then ignored.
if I handle the exceptions in the said methods themselves (the ones not properly awaited), could we then say that all is fine and well?
No, because the other issue still exists: the caller doesn't know when the asynchronous operation completes. This is particularly important to know in ASP.NET, because the result should not be sent until the operation is complete. Any kind of "fire and forget" code on ASP.NET lives outside the request/response lifetime; i.e., it's request-extrinsic code.
I go into some detail on my blog about why request-extrinsic code is dangerous. In summary, your ASP.NET handler may complete too soon, and in that case, the request-extrinsic code may get "lost". At the very least, whatever it's doing won't be done by the time the response is sent; and in the case of a regular shutdown (e.g., rolling upgrades), it might not get done at all.
Is there a way to fire an Http call to an external web API within my own web API without having to wait for results?
The scenario I have is that I really don't care whether or not the call succeeds and I don't need the results of that query.
I'm currently doing something like this within one of my web API methods:
var client = new HttpClient() { BaseAddress = someOtherApiAddress };
client.PostAsync("DoSomething", null);
I cannot put this piece of code within a using statement because the call doesn't go through in that case. I also don't want to call .Result() on the task because I don't want to wait for the query to finish.
I'm trying to understand the implications of doing something like this. I read all over that this is really dangerous, but I'm not sure why. What happens for example when my initial query ends. Will IIS dispose the thread and the client object, and can this cause problems at the other end of the query?
Is there a way to fire an Http call to an external web API within my own web API without having to wait for results?
Yes. It's called fire and forget. However, it seems like you already have discovered it.
I'm trying to understand the implications of doing something like this
In one of the links in the answers you linked above state the three risks:
An unhandled exception in a thread not associated with a request will take down the process. This occurs even if you have a handler setup via the Application_Error method.
This means that any exception thrown in your application or in the receiving application won't be caught (There are methods to get past this)
If you run your site in a Web Farm, you could end up with multiple instances of your app that all attempt to run the same task at the same time. A little more challenging to deal with than the first item, but still not too hard. One typical approach is to use a resource common to all the servers, such as the database, as a synchronization mechanism to coordinate tasks.
You could have multiple fire-and forget calls when you mean to have just one.
The AppDomain your site runs in can go down for a number of reasons and take down your background task with it. This could corrupt data if it happens in the middle of your code execution.
Here is the danger. Should your AppDomain go down, it may corrupt the data that is being sent to the other API causing strange behavior at the other end.
I'm trying to understand the implications of doing something like
this. I read all over that this is really dangerous
Dangerous is relative. If you execute something that you don't care at all if it completes or not, then you shouldn't care at all if IIS decides to recycle your app while it's executing either, should you? The thing you'll need to keep in mind is that offloading work without registration might also cause the entire process to terminate.
Will IIS dispose the thread and the client object?
IIS can recycle the AppDomain, causing your thread to abnormally abort. Will it do so depends on many factors, such as how recycling is defined in your IIS, and if you're doing any other operations which may cause a recycle.
In many off his posts, Stephan Cleary tries to convey the point that offloading work without registering it with ASP.NET is dangerous and may cause undesirable side effects, for all the reason you've read. That's also why there are libraries such as AspNetBackgroundTasks or using Hangfire for that matter.
The thing you should most worry about is a thread which isn't associated with a request can cause your entire process to terminate:
An unhandled exception in a thread not associated with a request will
take down the process. This occurs even if you have a handler setup
via the Application_Error method.
Yes, there are a few ways to fire-and-forget a "task" or piece of work without needing confirmation. I've used Hangfire and it has worked well for me.
The dangers, from what I understand, are that an exception in a fire-and-forget thread could bring down your entire IIS process.
See this excellent link about it.
I'm working on improving the exception-safety of a piece of code and I realized that a raised ThreadAbortException may cause undesired resource leaks, even when guarding resources with the C# using construct. For instance, consider the following code (which could be running in a separate thread).
using (TextWriter writer = CreateWriter(filename))
{
// do something with the writer.
}
TextWriter CreateWriter(string filename)
{
return new CustomWriter(File.OpenWrite(filename));
}
If the thread running this code is abnormally terminated, then I would like the file handle referenced by filename to be closed immediately. Can I do this without replacing the use of the using construct with a try/finally block?
My assumption is that ThreadAbortException may be raised at anytime, which means I should pay attention to what is happening between statements. While I can guard against the exception in CreateWriter with a try/finally block, the using construct won't do the same until after the expression in the parenthesis is evaluated, meaning the file resource is left open if the exception occurs immediately after CreateWriter returns.
I understand that a finalizer will ultimately release the file handle, but I am wondering if there is a deterministic way to address this issue without catching ThreadAbortException in each place that CreateWriter is used.
Yes, the deterministic way of preventing this is by not using Thread.Abort. Ever. Signal to your threads that is is time to stop, and let them terminate gracefully. Thread.Abort is a great big red-herring, placed in the API solely to trip you up. ;)
http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation
There is a tradeoff.
Be sure to close all resources immediately, even in the presence of ThreadAbortException
Have simpler code, but temporarily leak resources if Abort() is called
I assume that you are not calling Abort, and just want a way to be safe if someone else does. If you are calling Abort, then I'd advise that you don't. This isn't the only problem you will run into. There are other problems with Abort in the documentation.
#2 is a valid choice because callers of Abort() should expect this.
If you want to choose #1, then I don't think even a simple try/catch will help. If the ThreadAbortException can happen everywhere, then it can still happen after the file is opened (inside File.OpenWrite()) and before you can assign it to a variable that you can call Dispose() on -- you will have the same problem as using in your code.
You need semantics like
using (var handle = GetUnOpenedHandle()) {
handle.Open(); // this can't involve assignment to any field of handle
}
I'm not sure this is possible.
In many cases (but definitely not all) you could guard against a ThreadAbortException. Most of the critical code in the .NET BCL does this fairly well already. The problem is that it is really hard to get right. And for this reason most people recommend, and rightly so, to avoid aborting threads. Starting in version 2.0 the CLR made thread aborts a lot more tolerable and introduced a new set of APIs to help code authors guard against them. Take a look at Constrained Execution Regions for an in depth look at how all of this works.
I believe you are correct about your concerns with the example of the using block. For constrained execution regions to work correctly the out-of-band (asynchronous) exception must occur from within a try block. But, because of the way using expands out the expression is evaluated outside of the try block. Contrast that with the expansion of the lock block which evaluates the expression from within the try block. Well, that is true with version 4.0 of the framework anyway and that was changed specifically to guard against these exceptions.
So the question is why was the same change not made with the using block. According to Joe Duffy this was an acceptable omission because the assumption is that thread aborts should always be followed by a termination of the AppDomain which would fire off the finalizers anyway.
So yes. Your code is not tolerant of out-of-band (asynchronous) exceptions. But, the prevailing wisdom from those smarter than me is that it should not have to be.
A thread abort is most often used in the case of a fatal error, so your response should probably be to let your application terminate. If your trying to stop your own threads cleanly, use Thread.Join().
In a Winforms C# application, it seems like a good idea to catch exceptions in the GUI event methods such as button clicks, since this where all user action in an application begins.
If I put try-catch-finally clauses in the event methods then surely all my exceptions can be caught and dealt with appropriately?
Right?
In general, you should only catch exceptions that you know how to actually handle. You should catch them as close as possible to where they occur (because at that point, you know what the exception actually means).
If you are only catching exceptions in order to log them (and if this is a WinForms application), then I would use the Application.ThreadException event.
There are several ways to do it..
I prefer creating my error handler and throw all the exceptions from the code instead of catching it at that level.
Look at another post on how to handle them via Global Handler:
Where are exceptions best caught?
catches should be placed as close to the throwing source as possible. If your button click calls into your business layer which does some file processing, the business layer will better know how to recover from a FileNotFoundException than your button click handler.
Please check http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception.aspx
public static void Main(string[] args){
// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += new ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);
// Set the unhandled exception mode to force all Windows Forms errors to go through
// our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
// Runs the application.
Application.Run(new ErrorHandlerForm());}
Typically, the best advice is to catch exceptions where they can best be handled, and generally to favor catching them earlier if possible.
The reason is that an exception represents an error state that the code throwing it does not know how to deal with (if it did, then it would have dealt with the error). As a simple example, say you throw a NullReference exception. The coding throwing has no idea why the reference it needs is null. Maybe it's supposed to be, but the code doesn't account for it. Or maybe there's an error in your logic farther up that passes the null down.
Catching everything at the highest level, the UI events, is a good fallback to prevent exceptions from being exposed to the user, but it's a bad practice to get accustomed to because it obscures the real reasons why exceptions are being thrown and makes it difficult to figure out where the error should be corrected at.
yes your are. but Exception is for,
Catch specific exception to general exception.
[updated]
If exception is from different thread then it won't . right point, thanks " Brian Rasmussen" ;)
A try block will operate on any uncaught exceptions thrown by code within the try block. This includes methods you call, any methods those methods call, and so on. If the exception is thrown from one of those methods, it will "bubble up" through the program, breaking out of loops, methods, etc. until it reaches the last (i.e. deepest) try block to enclose it.
You could say that from the time you enter the try block until the time you leave it, any exceptions will immediately break out of the try and have the opportunity to be handled by it (unless they're caught by other try blocks nested inside it).
So to answer your question, if you know any exceptions are going to happen inside the event handler (or in methods called from inside that event handler), then wrapping the whole thing inside a try-catch-finally block will catch any exceptions (assuming an untyped catch).
Whether this is a good idea or not is a question of design. It usually isn't. You normally want to put your error-handlers fairly close to where the error might get thrown. However, without knowing your situation or your code, it's hard to give you any advice on design details like this.
Not to forget AppDomain.UnhandledException. I always handle this one, too, when doing central exception handling.
As part of a large automation process, we are calling a third-party API that does some work calling services on another machine. We discovered recently that every so often when the other machine is unavailable, the API call will spin away sometimes up to 40 minutes while attempting to connect to the remote server.
The API we're using doesn't offer a way to specify a timeout and we don't want our program waiting around for that long, so I thought threads would be a nice way to enforce the timeout. The resulting code looks something like:
Thread _thread = new Thread(_caller.CallServices());
_thread.Start();
_thread.Join(timeout);
if (_thread.IsAlive)
{
_thread.Abort();
throw new Exception("Timed-out attempting to connect.");
}
Basically, I want to let APICall() run, but if it is still going after timeout has elapsed, assume it is going to fail, kill it and move on.
Since I'm new to threading in C# and on the .net runtime I thought I'd ask two related questions:
Is there a better/more appropriate mechanism in the .net libraries for what I'm trying to do, and have I committed any threading gotchas in that bit of code?
Thread.Abort() is a request for the thread to abort, and gives no guarantee that it will do so in a timely manner. It is also considered bad practice (it will throw a thread abort exception in the aborted thread, but it seems like the 3rd party API offers you no other choices.
If you know (programmatically) the address of the remote service host you should ping it before you transfer control to the 3rd party API.
If not using a backgroundworker, you could set the thread's IsBackgroundThread to true, so it doesn't keep your program from terminating.
Bad idea. Thread.Abort doesn't necessarily clean up the mess left by such an interrupted API call.
If the call is expensive, consider writing a separate .exe that makes the call, and pass the arguments to/from it using the command line or temporary files. You can kill an .exe much more safely than killing a thread.
You can also just use a delegate... Create a delegate for the method that does the work, Then call BeginInvoke on the delegate, passing it the arguments, and a callback function to handle the return values (if you want)...
Immediately after the BeginInvoke you can wait a designated time for the asynch delegate to finish, and if it does not in that specified time, move on...
public delegate [ReturnType] CallerServiceDelegate
([parameter list for_caller.CallService]);
CallerServiceDelegate callSvcDel = _caller.CallService;
DateTime cutoffDate = DateTime.Now.AddSeconds(timeoutSeconds);
IAsyncResult aR = callSvcDel.BeginInvoke([here put parameters],
AsynchCallback, null);
while (!aR.IsCompleted && DateTime.Now < cutoffDate)
Thread.Sleep(500);
if (aR.IsCompleted)
{
ReturnType returnValue = callSvcDel.EndInvoke(aR);
// whatever else you need to do to handle success
}
else
{
callSvcDel.EndInvoke(aR);
// whatever you need to do to handle timeout
}
NOTE: as written AsynchCallback could be null, as the code retrieves the return value from the EndInvoke(), but if you want to you can have the CallService() method call the AsynchCallback delegate and pass it the return values instaed...
It might work, but nobody could say for sure without an understanding of the third-party API. Aborting the thread like that could leave the component in some invalid state that it might not be able to recover from, or maybe it won't free resources that it allocated (think - what if one of your routines just stopped executing half-way through. Could you make any guarantees about the state your program would be in?).
As Cicil suggested, it might be a good idea to ping the server first.
Does your application run for long periods of time or is it more of a run-as-needed application? If it's the latter, I personally would consider using the Thread.Abort() option. While it may not be the most desirable from a purist's perspective (resource management, etc.), it is certainly straightforward to implement and may foot the bill given the way your particular application works.
The idea of a separate executable makes sense. Perhaps another option would be to use AppDomains. I'm not an expert in this area (I welcome refinements/corrections to this), but as I understand it, you'd put the API call in a separate DLL and load it into a separate AppDomain. When the API call is finished or you have to abort it, you can unload the AppDomain along with the DLL. This may have the added benefit of cleaning up resources that a straightforward Thread.Abort() will not.