0

I build a small sample application in .Net 4.0 to test some task exception handling. I write the code below

       Task.Factory.StartNew(() =>
       {
           throw new Exception("Exception");
       }
       Thread.Sleep(100);
       GC.Collect();
       GC.WaitForPendingFinalizers();

I expected, as my application is net 4.0, that I will get an unhandled exception but nothing happens. I see in the post UnobservedTaskException is not killing the process that even if your application is .Net 4.0 if you have Net framework 4.5 installed, it will run on this later.
Indeed when I add :

 <runtime> 
    <ThrowUnobservedTaskExceptions enabled="true"/> 
 </runtime> 

The exception is thrown as with application in 4.5

Can someone explain what is the general principle about application version and installed framework version?

ucMedia
  • 4,105
  • 4
  • 38
  • 46
Che
  • 469
  • 4
  • 12

1 Answers1

2

The "general principle" is that .NET version 4.5 and up will behave as much as possible like .NET 4.0 when you originally targeted 4.0 in your project. It knows what you targeted thanks to the [TargetFrameworkAttribute] that the compiler embedded in your assembly.

That's pretty important of course, this design change in .NET 4.5 is heavily breaking. You would not want a .NET 4.0 app that previously ignored the exception and kept on chugging anyway to suddenly fail when it runs on a newer runtime version. A lot more common then you might assume, especially so since there wasn't a decent way to discover these exceptions. This was a very bad design choice and Microsoft corrected it in 4.5

It just has some config settings that you can use to override this compatibility behavior, ThrowUnobservedTaskExceptions is one of them. Back-porting the behavior to a 4.0 app was considered useful, it certainly is. If you run your app on a machine that only has 4.0 then it has no effect. Another example is here.

The code that does this is located here. The internal System.CLRConfig class is new in 4.5. Actual implementation is inside the CLR since the code that parses the .config file is located there as well.

Community
  • 1
  • 1
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Thanks Hans for those explanations. I did think that when we have installed on machine framework 4.0 and 4.5, the application build in 4.0 will run on top of framework 4.0 and not 4.5 but in my case it seems that application run on top of 4.5. May be there is any config to add ? – Che Jul 07 '16 at 13:44
  • No, that is not possible, 4.5 and 4.6 are not side-by-side versions. They *overwrite* the 4.0 install. The odds that you'll *ever* run on a machine that only has 4.0 are rather small today, it would have to be XP or Server2003 or a user that refuses to use Windows Update. Not the kind of customer you ever want to have to support. Best way to not have to is by targeting 4.5 :) – Hans Passant Jul 07 '16 at 13:53
  • Thanks, interesting, Then we can say that application run on top of the most recent Framework version installed in the machine whatever if it's built in lower version what can lead to unexpected changes when we upgrade the framework without changing anything to the application. – Che Jul 07 '16 at 14:10
  • Well, no, the entire point of CLRConfig is that there are **no** unexpected changes. If you don't use the config entry then it behaves *exactly* the way it would have if it ran on 4.0. – Hans Passant Jul 07 '16 at 14:18
  • Ok, but this is contradict behavior I got, without adding config, the Exception is not thrown during the collection of the task witch is not the behavior expected with 4.0 application. Please let me know if I have any misunderstanding. – Che Jul 07 '16 at 14:34
  • You got that backwards. 4.0 did not throw, the horrible behavior they fixed in 4.5 – Hans Passant Jul 07 '16 at 14:39