Wednesday 1 July 2015

Task exceptions

The following code demonstrates that you have to think carefully where exceptions that happen during task execution get handled, it may not always be where you think and this can lead to unexpected behavior on the "sad code execution path" (which infrequently gets enough attention) or swallowed / unobserved exceptions, or both.


using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Threading.Tasks;

namespace UnitTestProject1
{
    [TestClass]
    public class UnitTest2
    {
        [TestMethod]
        public async Task TestWork() 
        {
            TaskScheduler.UnobservedTaskException += (object sender, 
                UnobservedTaskExceptionEventArgs e) =>  {
                // not fired, as escalation policy doesn't kick in
                Assert.IsNotNull(e.Exception); 
            };
            var errorOccured = false;
            var work = Important.Work(async () => {
                // extraWork lambda
                await Task.Delay(100);
                throw new Exception("oops");
            }, () => {
                errorOccured = true;// onException func not hit
            })
            .ContinueWith(t => {
                // otherwise ex swallowed when continuation 
                // exists use only-on-faulted option
                Assert.IsTrue(t.IsFaulted);
                //t.Wait(); // observed exception on wait
            });
            //work.Wait(); // exception would NOT be observed here
            await work; // exception thrown here if NO continuation exists
            Assert.IsFalse(errorOccured);
        }
        [TestMethod]
        public async Task TestBetter()
        {
            TaskScheduler.UnobservedTaskException += (object sender, 
                UnobservedTaskExceptionEventArgs e) =>{
                // not fired, as escalation policy doesn't kick in
                Assert.IsNotNull(e.Exception); 
            };
            var errorOccured = false;
            var work = Important.BetterWork(async () =>{
                // extraWork lambda
                await Task.Delay(100);
                throw new Exception("oops");
            }, () =>{
                // on onException func hit before RETHROW in BetterWork()
                errorOccured = true; 
            })
            .ContinueWith(t =>{
                Assert.IsTrue(t.IsFaulted);
                //t.Wait(); // RETHROWN ex observed on wait 
                // otherwise RETHROWN exception swallowed
                // use only-on-faulted option
            });
            //work.Wait(); // RETHROWN exception would be observed here
            // RETHROWN exception caught here if NO continuation exists
            await work; 
            Assert.IsTrue(errorOccured);
        }

        public static class Important
        {
            public static Task Work(Func<Task> extraWork, 
                 Action onException)
            {
                //
                // work
                //
                try
                {
                    return extraWork();
                }
                catch (Exception)
                {
                    onException(); // not hit
                    throw;
                }
            }
            public static async Task BetterWork(Func<Task> extraWork, 
                 Action onException)
            {
                //
                // work
                //
                try
                {
                    await extraWork();
                }
                catch (Exception)
                {
                    onException(); // might not always be hit
                    throw;
                }
            }
        }

    }
}




1 comment:

John Cornejo said...

Thanks for sharing this great post. Your article provides us with excellent information. Thanks for taking the time to share it with us. There are many things that can be done online such as webcam tests that can be used to check a person's abilities, and these are very important in these pandemic times. If you need any help with the webcam, then you can click this link lenovo laptop camera not working to solve your problem.