Skip to main content

Multi Threaded NUnit Tests

Recently I needed to reproduce an Entity Framework deadlock issue. The test needed to run in NUnit, and involved firing off two separate threads. The trouble is that in NUnit, exceptions in threads terminate the parent thread without failing the test.

For example, here's a test that starts two threads: the first thread simply logs to the console, while the other thread turfs an exception. What I expected was that this test should fail. However, the test actually passes.

readonly ThreadStart[] delegates = {
    () => {
        Console.WriteLine("Nothing to see here");
    }, () => {
        throw new InvalidOperationException("Blow up");
    }
};

[Test] 
public void SimpleMultiThreading() {
    var threads = delegates.Select(d => new Thread(d)).ToList();
    foreach (var t in threads) {
        t.Start();
    }

    foreach (var t in threads) {
        t.Join();
    }
}

Peter Provost posted an article that describes how to make this test fail. It works by wrapping the thread code in a CrossThreadTestRunner class, that catches exceptions inside the thread, and rethrows the exception outside the thread via a Thread.Join call. Peter also posted another article describing how to use the CrossThreadTestRunner class.

Here's a partial code listing of the CrossThreadTestRunner class

public class CrossThreadTestRunner {
    private ThreadStart userDelegate;
    private Exception lastException;
    
    public CrossThreadTestRunner(ThreadStart userDelegate) {
        this.userDelegate = userDelegate;
    }
    
    public void Run() {
        Thread t = new Thread(new ThreadStart(MultiThreadedWorker));
        t.Start();
        t.Join();

        if (lastException != null) {
            ThrowExceptionPreservingStack(lastException);
        }
    }
    
    private void MultiThreadedWorker() {
        try {
            userDelegate.Invoke();
        }
        catch (Exception e) {
            lastException = e;
        }
    }
}

Peter's solution works if you are only using a single thread per test. If you wanted to run multiple threads in a test, some tweaks are required to the CrossThreadTestRunner class, since the CrossThreadTestRunner.Run method starts the thread, then does a Thread.Join to wait for the thread to complete. The problem with this is that it prevents threads from running in parallel, since Thread.Join blocks the calling thread until the target thread exits.

The change to allow for parallel thread execution is to split up the run method into a Start and a Join method, to mirror the corresponding methods on the Thread class. Here's the modified listing.

public class CrossThreadTestRunner {
    private ThreadStart userDelegate;
    private Exception lastException;
    private Thread thread;
    
    public CrossThreadTestRunner(ThreadStart userDelegate) {
        this.userDelegate = userDelegate;
        this.thread = new Thread(new ThreadStart(MultiThreadedWorker));
    }
    
    public void Start() {
        thread.Start();
    }
    
    public void Join() {
        thread.Join();

        if (lastException != null) {
            ThrowExceptionPreservingStack(lastException);
        }
    }
    
    private void MultiThreadedWorker() {
        try {
            userDelegate.Invoke();
        }
        catch (Exception e) {
            lastException = e;
        }
    }
}

Using the modified version of the CrossThreadTaskRunner, it's now possible to make the original test fail.

readonly ThreadStart[] delegates = {
    () => {
        Console.WriteLine("Nothing to see here");
    }, () => {
        throw new InvalidOperationException("Blow up");
    }
};

[Test] 
public void BetterMultiThreading() {
    var threads = delegates.Select(d => new CrossThreadTestRunner(d)).ToList();
    foreach (var t in threads) {
        t.Start();
    }

    foreach (var t in threads) {
        t.Join();
    }
}

One final tweak to turn this into a green test, is to add the ExpectedExceptionAttribute to the test method, to indicate that the test should fail with the given exception.

The final test looks something like the following

readonly ThreadStart[] delegates = {
    () => {
        Console.WriteLine("Nothing to see here");
    }, () => {
        throw new InvalidOperationException("Blow up");
    }
};

[Test]
[ExpectedException(typeof(InvalidOperationException))]
public void BetterMultiThreading() {
    var threads = delegates.Select(d => new CrossThreadTestRunner(d)).ToList();
    foreach (var t in threads) {
        t.Start();
    }

    foreach (var t in threads) {
        t.Join();
    }
}

Here's the full listing of the modified version of the CrossThreadTestRunner class.

class CrossThreadTestRunner {
        private Exception lastException;
        private readonly Thread thread;
        private readonly ThreadStart start;

        private const string RemoteStackTraceFieldName = "_remoteStackTraceString";
        private static readonly FieldInfo RemoteStackTraceField = typeof(Exception).GetField(RemoteStackTraceFieldName, BindingFlags.Instance | BindingFlags.NonPublic);

        public CrossThreadTestRunner(ThreadStart start) {
            this.start = start;
            this.thread = new Thread(Run);
            this.thread.SetApartmentState(ApartmentState.STA);
        }

        public void Start() {
            lastException = null;
            thread.Start();
        }

        public void Join() {
            thread.Join();

            if (lastException != null) {
                ThrowExceptionPreservingStack(lastException);
            }
        }

        private void Run() {
            try {
                start.Invoke();
            }
            catch (Exception e) {
                lastException = e;
            }
        }

        [ReflectionPermission(SecurityAction.Demand)]
        private static void ThrowExceptionPreservingStack(Exception exception) {
            if (RemoteStackTraceField != null) {
                RemoteStackTraceField.SetValue(exception, exception.StackTrace + Environment.NewLine);
            }
            throw exception;
        }
    }

The code for this article is on GitHub.

Comments

  1. Needed to compose you a very little word to thank you yet again regarding the nice suggestions you’ve contributed here.

    Hadoop Training in Chennai

    ReplyDelete
  2. After reading this web site I am very satisfied simply because this site is providing comprehensive knowledge for you to audience. Thank you to the perform as well as discuss anything incredibly important in my opinion. We loose time waiting for your next article writing in addition to I beg one to get back to pay a visit to our website in
    java training in omr

    java training in annanagar | java training in chennai

    java training in marathahalli | java training in btm layout

    java training in rajaji nagar | java training in jayanagar

    ReplyDelete
  3. Really great post, Thank you for sharing This knowledge.Excellently written article, if only all bloggers offered the same level of content as you, the internet would be a much better place. Please keep it up!
    python training in omr

    python training in annanagar | python training in chennai

    python training in marathahalli | python training in btm layout

    python training in rajaji nagar | python training in jayanagar

    ReplyDelete
  4. Have you been thinking about the power sources and the tiles whom use blocks I wanted to thank you for this great read!! I definitely enjoyed every little bit of it and I have you bookmarked to check out the new stuff you post
    Data Science Training in Chennai
    Data science training in bangalore
    Data science online training
    Data science training in pune
    Data science training in kalyan nagar
    selenium training in chennai

    ReplyDelete
  5. Wow it is really wonderful and awesome thus it is very much useful for me to understand many concepts and helped me a lot. it is really explainable very well and i got more information from your blog.


    rpa training in Chennai | rpa training in velachery

    rpa training in tambaram | rpa training in sholinganallur

    rpa training in Chennai | rpa training in pune

    rpa online training | rpa training in bangalore

    ReplyDelete
  6. Thanks for your informative article, Your post helped me to understand the future and career prospects & Keep on updating your blog with such awesome article.
    python training in annanagar
    python training in chennai
    python training in chennai
    python training in Bangalore

    ReplyDelete
  7. Your good knowledge and kindness in playing with all the pieces were very useful. I don’t know what I would have done if I had not encountered such a step like this.
    Devops training in sholinganallur
    Devops training in velachery

    ReplyDelete
  8. Hmm, it seems like your site ate my first comment (it was extremely long) so I guess I’ll just sum it up what I had written and say, I’m thoroughly enjoying your blog. I as well as an aspiring blog writer, but I’m still new to the whole thing. Do you have any recommendations for newbie blog writers? I’d appreciate it.

    Best Selenium Training in Chennai | Selenium Training Institute in Chennai | Besant Technologies

    Selenium Training in Bangalore | Best Selenium Training in Bangalore

    AWS Training in Bangalore | Amazon Web Services Training in Bangalore

    ReplyDelete
  9. Nice information, valuable and excellent design, as share good stuff with good ideas and concepts, lots of great information and inspiration, both of which I need, thanks to offer such a helpful information here.
    devops online training

    aws online training

    data science with python online training

    data science online training

    rpa online training

    ReplyDelete
  10. Really impressive post. I read it whole and going to share it with my social circules. I enjoyed your article and planning to rewrite it on my own blog.
    data science course malaysia

    ReplyDelete
  11. Alleyaaircool is the one of the best home appliances repair canter in all over Delhi we deals in repairing window ac, Split ac , fridge , microwave, washing machine, water cooler, RO and more other home appliances in cheap rates

    Window AC Repair in vaishali
    Split AC Repair in indirapuram
    Fridge Repair in kaushambi
    Microwave Repair in patparganj
    Washing Machine Repair in vasundhara
    Water Cooler Repair in indirapuram
    RO Service AMC in vasundhara
    Any Cooling System in vaishali
    Window AC Repair in indirapuram

    ReplyDelete
  12. Home Mart is a site about Home Improvement, Furniture, Home Appliances and many more.
    Check out the best
    furniture sale
    Dog Cages
    bedroom furniture nz
    entertainment unit

    ReplyDelete
  13. Thanks for splitting your comprehension with us. It’s really useful to me & I hope it helps the people who in need of this vital information.web design company in velachery

    ReplyDelete
  14. I would definitely thank the admin of this blog for sharing this information with us. Waiting for more updates from this blog admin.
    salesforce Training in Bangalore
    uipath Training in Bangalore
    blueprism Training in Bangalore

    ReplyDelete
  15. Wow...What an excellent informative blog, really helpful. Thank you so much for sharing such a wonderful article with us.keep updating..
    aws Training in Bangalore
    python Training in Bangalore
    hadoop Training in Bangalore
    angular js Training in Bangalore
    bigdata analytics Training in Bangalore

    ReplyDelete
  16. רציתי רק לשאול, אפשר לשתף את הפוסט בבלוג שלי?
    קבוצת גבאי פייסבוק

    ReplyDelete
  17. This comment has been removed by the author.

    ReplyDelete
  18. לגמרי פוסט שדורש שיתוף תודה.
    יהלומי מעבדה

    ReplyDelete
  19. לגמרי פוסט שדורש שיתוף תודה.
    מזנון צף

    ReplyDelete
  20. מזל שנתקלתי בכתבה הזאת. בדיוק בזמן
    מילוי שפתיים

    ReplyDelete
  21. תודה על השיתוף. מחכה לכתבות חדשות.
    הפקת אירועים

    ReplyDelete
  22. אין ספק שזה אחד הנושאים המעניינים. תודה על השיתוף.
    מוצרי תינוקות

    ReplyDelete
  23. Great Information,it has lot for stuff which is informative.I will share the post with my friend
    cat hanging necklace

    ReplyDelete
  24. אין ספק שהפוסט הזה דורש שיתוף. תודה.
    תמונה מודפסת על עץ

    ReplyDelete
  25. מזל שנתקלתי בכתבה הזאת. בדיוק בזמן
    מצלמות אבטחה לעסק

    ReplyDelete
  26. keep up the good work. this is an Assam post. this to helpful, i have reading here all post. i am impressed. thank you. this is our digital marketing training center. This is an online certificate course
    digital marketing training in bangalore | https://www.excelr.com/digital-marketing-training-in-bangalore

    ReplyDelete

  27. You write this post very carefully I think, which is easily understandable to me. Not only this, but another post is also good. As a newbie, this info is really helpful for me. Thanks to you.
    Tally ERP 9 Training
    tally classes
    Tally Training institute in Chennai
    Tally course in Chennai

    ReplyDelete
  28. Nice blog,I understood the topic very clearly,And want to study more like this.
    Data Scientist Course

    ReplyDelete
  29. תודה על השיתוף. מחכה לכתבות חדשות.
    חברת קידום אתרים

    ReplyDelete
  30. כתיבה מעולה, אהבתי. אשתף עם העוקבים שלי.
    מארזים ליולדת

    ReplyDelete
  31. סגנון כתיבה מרענן, תודה על השיתוף.

    קרקעות להשקעה

    ReplyDelete
  32. Attend The Data Science Courses From ExcelR. Practical Data Science Courses Sessions With Assured Placement Support From Experienced Faculty. ExcelR Offers The Data Science Courses.
    Data Science Courses
    Data Science Interview Questions

    ReplyDelete
  33. רציתי רק לשאול, אפשר לשתף את הפוסט בבלוג שלי?
    בית תוכנה

    ReplyDelete
  34. I like viewing web sites which comprehend the price of delivering the excellent useful resource free of charge. I truly adored reading your posting. Thank you!
    data analytics course
    supply chain analytics beginner's guide
    big data course in malaysia
    360DigiTMG
    big data analytics training in malaysia

    ReplyDelete
  35. Good post. I learn something new and challenging on sites I stumbleupon on a daily basis. It's always interesting to read content from other writers and practice a little something from their web sites.
    Digital Marketing Training Course in Chennai | Digital Marketing Training Course in Anna Nagar | Digital Marketing Training Course in OMR | Digital Marketing Training Course in Porur | Digital Marketing Training Course in Tambaram | Digital Marketing Training Course in Velachery

    ReplyDelete
  36. הייתי חייבת לפרגן, תודה על השיתוף.
    תמונה על קנבס

    ReplyDelete
  37. Awesome blog. I enjoyed reading your articles. This is truly a great read for me. I have bookmarked it and I am looking forward to reading new articles. Keep up the good work!
    Data Science Course in Pune
    Data Science Training in Pune

    ReplyDelete
  38. I feel very grateful that I read this. It is very helpful and very informative and I really learned a lot from it.
    Data Analytics Course in Pune
    Data Analytics Training in Pune

    ReplyDelete
  39. I am impressed by the information that you have on this blog. It shows how well you understand this subject.
    Business Analytics Course in Pune
    Business Analytics Training in Pune

    ReplyDelete
  40. I don t have the time at the moment to fully read your site but I have bookmarked it and also add your RSS feeds. I will be back in a day or two. thanks for a great site.
    data science bootcamp malaysia

    ReplyDelete
  41. I am impressed by the information that you have on this blog. It shows how well you understand this subject.
    data analytics course
    big data analytics malaysia
    big data course

    ReplyDelete
  42. cool stuff you have and you keep overhaul every one of us
    data science bootcamp malaysia

    ReplyDelete
  43. I am impressed by the information that you have on this blog. It shows how well you understand this subject.
    data analytics course
    big data analytics malaysia
    big data course

    ReplyDelete
  44. Nice blog. I finally found great post here Very interesting to read this article and very pleased to find this site. Great work!
    Data Science Training in Pune
    Data Science Course in Pune

    ReplyDelete
  45. I am really enjoying reading your well written articles. It looks like you spend a lot of effort and time on your blog. I have bookmarked it and I am looking forward to reading new articles. Keep up the good work.
    Data Science Certification in Bangalore

    ReplyDelete
  46. Really impressive post. I read it whole and going to share it with my social circules. I enjoyed your article and planning to rewrite it on my own blog.

    Cat Doors

    ReplyDelete
  47. I was just browsing through the internet looking for some information and came across your blog. I am impressed by the information that you have on this blog. It shows how well you understand this subject. Bookmarked this page, will come back for more.
    Data Science Course in Bangalore

    ReplyDelete
  48. Pretty good post. I just stumbled upon your blog and wanted to say that I have really enjoyed reading your blog posts. Any way I’ll be subscribing to your feed and I hope you post again soon.
    Data Science Training in Bangalore

    ReplyDelete
  49. Very interesting blog. Many blogs I see these days do not really provide anything that attracts others, but believe me the way you interact is literally awesome.You can also check my articles as well.

    Data Science In Banglore With Placements
    Data Science Course In Bangalore
    Data Science Training In Bangalore
    Best Data Science Courses In Bangalore
    Data Science Institute In Bangalore

    Thank you..

    ReplyDelete

Post a Comment

Popular posts from this blog

Basic Web Performance Testing With JMeter and Gatling

Introduction In this post I'll give a quick way to get some basic web performance metrics using both JMeter and Gatling.

JMeter is a well known, open source, Java based tool for performance testing. It has a lot of features, and can be a little confusing at first. Scripts (aka Test Plans), are XML documents, edited using the JMeter GUI.  There are lots of options, supports a wide variety of protocols, and produces some OK looking graphs and reports.

Gatling is a lesser known tool, but I really like it. It's a Scala based tool, with scripts written in a nice DSL. While the scripts require some basic Scala, they are fairly easy to understand and modify. The output is a nice looking, interactive, HTML page.
Metrics Below are the basic metrics gathered by both JMeter and Gatling. If you are just starting performance testing, these might be a good starting point.

Response Time – Difference between time when request was sent and time when response has been fully received

Latency –…

Generating Java Mixed Mode Flame Graphs

Overview I've seen Brendan Gregg's talk on generating mixed-mode flame graphs and I wanted to reproduce those flamegraphs for myself. Setting up the tools is a little bit of work, so I wanted to capture those steps. Check out the Java in Flames post on the Netflix blog for more information.

I've created github repo (github.com/jerometerry/perf)  that contains the scripts used to get this going, including a Vagrantfile, and JMeter Test Plan.

Here's a flame graph I generated while applying load (via JMeter) to the basic arithmetic Tomcat sample application. All the green stacks are Java code, red stacks are kernel code, and yellow stacks are C++ code. The big green pile on the right is all the Tomcat Java code that's being run.


Tools Here's the technologies I used (I'm writing this on a Mac).
VirtualBox 5.1.12Vagrant 1.9.1bento/ubuntu-16.04 (kernel 4.4.0-38)Tomcat 7.0.68JMeter 3.1OpenJDK 8 1.8.111linux-tools-4.4.0-38linux-tools-commonBrendan Gregg's Fla…