2

Is there a way to check if any "user" threads are running. I'd like to put this in the [TestCleanup] method, failing the test if a test hasn't joined all the threads it started.

I figured just listing all the currently running threads wouldn't help, as there's probably for example, garbage collection threads that start at indeterminate times. So I basically want the threads that aren't just associated with the runtime.

13
  • 1
    And you're definitely using threads and not tasks, right? Commented Oct 28, 2019 at 0:50
  • In the current codebase yes Commented Oct 28, 2019 at 0:51
  • This test seems like its pointing to bigger problems, this shouldn't really need to be tested for, and if you do, it should probably be covered in another test Commented Oct 28, 2019 at 0:55
  • I don't know what you mean, I want to cover this in all tests. It may or may not be a test code that starts the threads, but in either case they should be cleaned up once the test is complete. If they're not this seems like something we should be aware of hence the test should fail. Commented Oct 28, 2019 at 1:02
  • It would be awesome if you could share a minimal reproducible example. Commented Oct 28, 2019 at 1:17

2 Answers 2

1

I would recommend taking a look at the Microsoft.Diagnostics.Runtime library (Nuget). Specifically the CLR capabilities. You can get a list of all threads with stacktraces with the following code

using (DataTarget target = DataTarget.AttachToProcess(Process.GetCurrentProcess().Id, 5000, AttachFlag.Passive)) { ClrRuntime runtime = target.ClrVersions.First().CreateRuntime(); return new runtime.Threads; } 
Sign up to request clarification or add additional context in comments.

Comments

1

There are some really valid points in the comments section of the question but you could

  1. Try and see if thread counting works for you without worrying about
  2. Try TryStartNoGCRegion:
    GC.TryStartNoGCRegion(1024*1204*10); var count = System.Diagnostics.Process.GetCurrentProcess().Threads.Count; GC.EndNoGCRegion(); 

Here's a trivial example.

public static void Main() { int GetThreadCount() { GC.TryStartNoGCRegion(1024*1204*10); var count = System.Diagnostics.Process.GetCurrentProcess().Threads.Count; GC.EndNoGCRegion(); return count; } var count1 = GetThreadCount(); Console.WriteLine($"Headcount at (in?) the beginning: {count1}"); var t1 = new Thread(() => { Thread.Sleep(1000); }); t1.Start(); var count2 = GetThreadCount(); Console.WriteLine($"Headcount later: {count2}"); if (count2 != count1 ) { Console.WriteLine("Oh no! Threads running!"); } t1.Join(); var count3 = GetThreadCount(); Console.WriteLine($"Headcount even later: {count3}"); if (count3 != count1 ) { Console.WriteLine("Oh no! Threads running!"); } else { Console.WriteLine("Phew. Everybody Joined the party."); } Console.ReadLine(); } 

Output

// .NETCoreApp,Version=v3.0 Headcount at (in?) the beginning: 10 Headcount later: 11 Oh no! Threads running! The thread 9620 has exited with code 0 (0x0). Headcount even later: 10 Phew. Everybody Joined the party. 

1 Comment

This is a nice idea. I'll give it a go and see how consistent it is over out test suite.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.