Reactive Extensions swallows exceptions from OnNext() called on a thread pool thread? - c#

I use Rx 2 in .Net 4.5. When the following code runs, it just exits silently without executing the OnCompleted delegate or showing any errors. If I use Scheduler.CurrentThread in ToObservable, it will at least throw the error and terminate the program, at which point not executing OnCompleted makes sense. But when this is executed in a thread other than the main one, this behavior seems unreasonable and unacceptable. Do I miss anything?
static void Main()
{
Enumerable.Range(0, 1)
.ToObservable(Scheduler.Default)
.Subscribe(o => { throw new Exception("blah"); }, () => Console.WriteLine("completed"));
Thread.Sleep(2000);
}
Edited:
Yes, when running as a console app, it will always throw the error regardless of what thread the observation is executed on.
However, when I run this code as a test in NUnit as follows, it exits silently after 2 seconds (thread sleep time) without any error or message (expecting "completed"). So is it actually NUnit causing the issue?
[TestFixture]
class Program
{
[Test]
public void Test()
{
Enumerable.Range(0, 1)
.ToObservable(Scheduler.Default)
.Subscribe(
o => { throw new Exception("blah"); },
() => Console.WriteLine("completed"));
Thread.Sleep(2000);
}
}

Rx does not catch exceptions thrown by observers. This is a very important design principle that has been discussed in length before, though for some reason it's only included as a footnote of ยง6.4 in the Rx Design Guidelines.
Note: do not protect calls to Subscribe, Dispose, OnNext, OnError and OnCompleted methods. These calls are on the edge of the monad. Calling the OnError method from these places will lead to unexpected behavior.
Essentially, this guideline ensures that, from the perspective of an observer, OnError will only be called by exceptions originating from the observable itself, including any calls to user code that participate directly in the computation (rather than merely observing the results). If this were not the case, then an observer may not be able to distinguish whether an exception passed to OnError is a bug in their OnNext handler or perhaps a bug in the observable.
But more importantly, it also ensures that any exception thrown by an OnNext handler goes unhandled. This makes it easier to debug your program and protects user data.
That being said, the reason why you may be observing different behavior when OnNext is executed on a pooled thread is simply a consequence of your debugging experience. Try enabling first-chance exceptions.
Furthermore, I'd also avoid the race condition by changing Thread.Sleep to Console.ReadKey().

Exceptions thrown in the Subscribe block have Undefined Behavior. If you are doing something that can throw, you need to wrap that in a Select or SelectMany (or just wrap the code in a try-catch).

Related

Considerations for not awaiting a Task in an asynchronous method

I'm working on a Web API project which uses Azure's managed cache service to cache database results in memory to improve response times and alleviate duplicate traffic to the database. When attempting to put a new item in the cache, occasionally a cache-specific exception will be thrown with a code of DataCacheErrorCode.RetryLater. Naturally, in order to retry later without needing to block on this method I made it async and await Task.Delay to try again a short time later. Previously a developer had hardcoded a Thread.Sleep in there that was really hurting application performance.
The method signature looks something similar to this now:
public static async Task Put(string cacheKey, object obj)
Following this change I get ~75 compiler warnings from all the other places in the application that called the formerly synchronous version of Put indicating:
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.
In this case, since Put doesn't return anything, it makes sense to me to let this operation fire-and-forget as I don't see any reason to block execution of the method that called it. I'm just wondering if there are any dangers or pitfalls for allowing a lot of these fire-and-forget Tasks running in the background as Put can be called quite often. Or should I await anyway since 99% of the time I won't get the retry error and the Task will finish almost immediately. I just want to make sure that I'm not incurring any penalties for having too many threads (or something like that).
If there is a chance Put will throw any other exception for any kind of reason, and you don't use await Put each time you're inserting an object to the cache, the exceptions will be swallowed inside the returned Task which isn't being awaited. If you're on .NET 4.0, this exception will be re-thrown inside the Finalizer of that Task.. If you're using .NET 4.5, it will simply be ignored (and that might not be desirable).
Want to make sure that I'm not incurring any penalties for having too
many threads or something like that.
Im just saying this to make things clear. When you use Task.Delay, you aren't spinning any new threads. A Task isn't always equal to a new thread being spun. Specifically here, Task.Delay internally uses a Timer, so there aren't any thread overheads (except for the thread which is currently being delayed if you do use await).
The warning is telling you that you're getting fire and forget behavior in a location where you may not actually want to fire and forget. If you really do want to fire and forget and don't have a problem continuing on without ever knowing when the operation finishes, or if it even finished successfully, then you can safely ignore the warning.
One negative result of releasing a task to run unawaited is the compiler warnings themselves - 75 compiler warnings are a problem in and of themselves and they hide real warnings.
If you want to signal the compiler that you're intentionally not doing anything with the result of the task, you can use a simple extension method that does nothing, but satisfies the compiler's desire for explicitness.
// Do nothing.
public static void Release(this Task task)
{
}
Now you can call
UpdateCacheAsync(data).Release();
without any compiler warnings.
https://gist.github.com/lisardggY/396aaca7b70da1bbc4d1640e262e990a
Recommended ASP.NET way is
HostingEnvironment.QueueBackgroundWorkItem(WorkItem);
...
async Task WorkItem(CancellationToken cancellationToken)
{
try { await ...} catch (Exception e) { ... }
}
BTW Not catching/re-throw on thread other then ASP.NET thread can cause server process to be crashed/restarted

Is it necessary to call EndInvoke in the callback from an EventHandler.BeginInvoke (C# .Net 3.5)

I'm setting up a WCF client and server scenario that needs to be reliable and scalable and as part of that I'm trying to make it multithreaded. Admittedly I don't have extensive multithreading experience.
On the client, the callback from the server (in this case "OnMessage") fires a client-side event that should be passed off in the background. I have the client's CallbackBehavior ConcurrencyMode set to Single (at least, for now). So in order to do a reply to the callback, rather than calling the handler as normal (either handler(sender, eventargs, or handler.Invoke...) I'm calling handler.BeginInvoke.
Everything works fine, but in the callback I'm wondering if I need to explicitly call EndInvoke or if I can basically do nothing (here's my lack of multithreading experience showing).
public void OnMessage(Message message)
{
EventHandler<MessageEventArgs> handler = OnServerMessage;
if (handler != null)
handler.BeginInvoke(this, new MessageEventArgs(message), CompleteHandler, handler);
}
public void CompleteHandler(IAsyncResult result)
{
((EventHandler<MessageEventArgs>)result.AsyncState).EndInvoke(result);
}
Can I replace CompleteHandler with a direct reference to handler.EndInvoke, or an empty method, or perhaps is there something more I should be doing?
Also, at the moment, the event subscriber blocks waiting on user input from the console. When the application is complete, it would either block waiting on the database, or be asynchronous bottom-to-top (so this may not be necessary, but I'd still like to know).
Yes you have to. Only way to find out if the invoked method threw an exception. And to cleanup the remoting state of the call so it can be garbage collected instead of letting it linger for another 10 minutes.
You need to wrap your CompleteHandler code in a try/catch block and then properly handle any exception thrown by the EndInvoke. Right now the service works under 'lab' conditions, but when things go wrong you won't even know what goes wrong, because you don't handle/log errors properly.
As for the issue of getting the state from the global state, or from the IAsyncResult, or from a callback closure: IASyncResult.AsyncState is the most generic solution and will continue to work correctly after somebody else refactors the calling code beyond any recognition.
In general, BeginInvoke starts an asynchronous operation, whereas EndInvoke waits for it to finish. So it depends on your intention: if you want to guarantee that your asynchronous code is finished, you need EndInvoke, otherwise no.
(Beware however that if your BeginInvoke calls into the same thread where you actually are (it's a valid usage, just the code will be run on the next Dispatcher loop), you must not use EndInvoke, as this would create a deadlock. But this seems to be not your case.)

Why do exceptions propogate out of an event handler?

Consider the following program. How is the behaviour that it displays (namely that exceptions will propagate out of an event handler) a "good thing"? As far as I can tell, it could only ever be bad; unexpected exceptions popping up from functions that they shouldn't. In my particular case, it was killing threads. So, is this behaviour actually a good thing in some cases? Is this a reason to say that letting exceptions out of event-handlers is poor design?
static class Program {
static void Main()
{
Foo foo = new Foo();
foo.SomeEvent += ThrowException;
try
{
foo.OnSomeEvent();
}
catch (Exception)
{
// This is printed out
Console.WriteLine("Exception caught!");
}
}
static void ThrowException(object sender, EventArgs e)
{
throw new Exception();
}
}
// Define other methods and classes here
class Foo
{
public event EventHandler SomeEvent;
public void OnSomeEvent()
{
SomeEvent(this, EventArgs.Empty);
}
}
What's your preferred alternative - silently swallowing the exception? I wouldn't like that at all.
Events are just a way of implementing the observer pattern, really. If a listener throws an exception, I'd absolutely expect that exception to be thrown back to the caller. Any other behaviour I can think of would effectively treat the exception as unimportant. The whole point of exceptions is that when something goes wrong, you find out about it quickly and implicitly. You have to explicitly handle exceptions, so that you don't go on your merry way in a corrupt state without realising it.
You make a valid point about whose responsibility it is to handle exceptions. Broadly speaking, I find it best to assume that just about anything can throw an exception at any time. Other than special cases where I know a specific exception may occur and I can handle it, I don't usually catch exceptions other than at the top level - except possibly to wrap and rethrow, or log and rethrow.
Now it's possible that one of your event handlers really shouldn't be throwing an exception - that they haven't really run into an error condition - but what should happen if it's a perfectly reasonable exception which indicates a serious problem? While a program crashing is ugly, it's often better than continuing with some of it malfunctioning, possibly corrupting persisted state etc.
Fundamentally, I don't think the CS/SE field has got error handling "right" yet. I'm not even sure that there is an elegant way of doing the right thing which is simple to express in all situations... but I hope that the current situation isn't as good as it gets.
The main aspect of exception handling discussed here is: do not catch exception if you don't know how to handle it. But let's talk about the observer pattern, where notifier emits event (or signal) about it's state change and listeners handle it. A good example of a notifier is a button emitting 'clicked' event. Does a button care about who are the listeners and what they do? Not really. If you're a listener and you got this event, then you've got a job to do. And if you can't do it, you have to handle this error or inform user, because passing exception to the button makes no sense - button definitely does not know how to handle errors of listener job. And buttons state changer (probably some message loop) does not either - your application will end up at Main() with a crash.
That's how observer pattern works - event emitters don't know what their listeners are doing and there's very little chance they will handle this exception properly.
Also bear in mind, that if your exception handler throws exception, there may be other listeners that won't receive notification and that may lead to undefined application state.
So my advice is to catch all exceptions at event handler, but figure out how to handle them there. Or else no one will.
My personal prejudice is that not catching exceptions is generally a bad thing. The only "exception" to this rule for me is for simple applciations where the uncaught exception termianates the process, you see the error and fix it.
For multi-threaded apps, if the default behaviour of uncaught exceptions is to zap threads then it seems to me absurd not to catch exceptions. Hence event handlers should not just punt the exception up the stack and hope for the best.
Silently swallowing exceptions is usually bad too, something bad has happended it needs fixing. So perhaps log a message, and then return?
You need a contract with the event source on whether the event handler can throw exceptions. For example, if a COM object is an event source this is strictly prohibited - exceptions should never cross COM boundary.
An event is nothing more than syntactic sugar around a function call, so it makes sense that it would propagate up to the function that raised the event. What, otherwise, should the behaviour be? The exception has to go somewhere.
It would be the best to think about exception as part of your contract with event listeners.
Which means, if the listener is nice and catches its Exceptions (it can do that for known ones), you are OK.
For the rest, unknown exceptions, or in Java speech "Runtime exceptions", you need to be ready for them the same way as if they would occur in your code.
What I am trying to say is, if you are building a contract with the event listeners, you cannot force them to throw just one exception type (so that you can consume them) and you need to take all Exceptions seriously. After all, they are indications of "wrong states" which you don't want to hide for consumers.

ThreadAbortException vs graceful event handle exit in C#

When aborting the execution of a thread I'm always doubting between a graceful exit with an event handler like this:
int result = WaitHandle.WaitAny(handles);
if (result = WAIT_FINALIZE)
FinalizeAndExit();
and using the event to signal the thread it must terminate
or just handling the ThreadAbortException to finalize the thread...
try
{
// Main execution
}
catch(ThreadAbortException e)
{
// FinalizeAndExit();
}
finally
{
}
I'm usually inclined to use the ThreadAbortException approach since it can be handled but it is re-raised at the end of the catch block, and it also avoids the thread from being kept alive by "treacherous" methods, but I've seen both approaches.
What's your opinion? Is there any situation where it's best to use one over another, or is it best to use always approach x?
Generally, the first method it preferrable.
It's hard (if not impossible) to write code that will always handle a ThreadAbortException gracefully. The exception can occur in the middle of whatever the thread happens to be doing, so some situations can be hard to handle.
For example, the exception can occur after you have created a FileStream object, but before the reference is assigned to a variable. That means that you have an object that should be disposed, but the only reference to it is lost on the stack somewhere...
If I can I try to avoid using Thread.Abort.
The problem with Thread.Abort is that it could happen in (almost) any line of the executing code and might cause some "interesting" behavior (read: bugs).
Intead I prefer to have a point of exit on my code that checks for an event or variable to see if it the thread should stop running and gracefully exit.
Surely if the termination event is expected then it's not an exception (by the strict definition of the term) so therefore you should be using the first method. A graceful exit also shows that you are in control.
While exceptions are useful and in some cases necessary, they can and do get overused.

Exception catching best practice (c#/.net)

If I have code like this:
void a()
{
try
{
b();
}
catch (MyException)
{
// Handle any problems that occurred in b(c(d()))
}
}
void b()
{
c();
// Do something else
}
void c()
{
d();
// Do something else
}
void d()
{
// Do something, throw a MyException if it fails
}
Assuming no cleanup is necessary at any point, is it best to put a try{}catch{throw;} around the call to d() in c() and the call to c() in b() or is it considered OK to let the exception from d() bubble up to a() "naturally" without any intervening try/catch blocks?
I suppose the extra try/catch block act as a sort of "documentation" but they seem superfluous so I'm just wondering what other people would consider the best way.
Sorry if this is all a bit too basic, I'm trying to get my head around exceptions but I don't seem to have a good feel for them yet.
Let it propagate until you can handle it. If you can't handle it, there's no point catching it. So the question is, can you effectively handle the exception inside the c() method?
Basically, no. This is not the suggested way to handle these situations.
You should catch exceptions if and only if you can either handle them and do something appropriate with them or to provide more info to the callers higher in the call stack (by encapsulating it in a more generic exception). If you can't do it, you should let the exception bubble up in the call stack until someone can handle it appropriately.
The great advantage of exceptions is that you can deal with problems where you can do womething about them, rather than directly in the function where e.g. a missing file is detected, or in the function's caller, or its caller, &c.
However, exceptions also have to be handled somewhere along the chain. Where these points occur depend on the framework you are using, and what its exception management consists of. The key question is: what are your points of entry where allowing an exception to escape uncaught would have bad effects? Typical examples include
Event processing code in interactive UI applications (which at least in WinForms and ASP.NET can be caught en masse by providing exception event handlers).
Integration points where you respond to external messages (e.g. picking up messages from a queue, processing a file, listening on a named pipe, implementing a WCF service).
Timer events where you do background processing.
Thread start methods.
Sometimes, you also want to catch a low-level general technical error and rethrow it as a more domain-specific exception. This typically done in well-designed libraries to shield users from its internal implementation details. In an enterprise application, you might want to catch certain SqlExceptions and rethrow them as application-specific exceptions (e.g. YourApp.UnknownCustomer), in order to deal with them at higher levels of logic.
My advice would be: deal with problems at the highest level possible, but ensure that the exception catchers up there have reasonable exceptions to work with. And, by the way, unless you hate your users, don't display the exception and its stack trace to them! ;-)
I'd say, it depends on what you want to do with the information.
I always try to catch problems as close to the source as possible - why run all the way back with the problem, instead of trying to deal with it where it happens? For readability and understanding of the code, I also believe in try/catch as close to the source of the problem as possible.
If you're writing the program for yourself, and noone else will ever touch it, do whatever works best for you and the code.

Categories

Resources