I’ve recently been working with WebAssembly (WASM) to target the WebAssembly Server Interface (WASI), specifically the Wasmtime runtime. Running .NET applications in an operating system agnostic way opens up a world of possibilities and begins to blur the lines between client and server. Of course, it’s still very early, and anything could happen, but to say I’m excited about the future of WASM is an understatement.

One drawback with WASI runtimes is they are still limited to single-threaded execution. I wasn’t sure how to confirm that my application was single-threaded, but I’ve found a few ways to tell if your current application has threads necessary for multiple-thread executions.

WASM Runtime Warning

The following code I’m about to show you depends on the runtime and platform your application is running within. If you’re running in a supported platform, I suggest the first method I’ll be showing you as it accounts for all potential threads in your application, managed and unmanaged.

See, WASM and their runtimes are still evolving, and in most .NET cases, the runtime you’ll be using is the same one Blazor uses, a modified version of Silverlight/Mono. This runtime is only a subset of what you might use with runtimes like .NET SDK or Full Framework. Therefore, when targeting WASM with .NET, it is vital to test your code and not assume all the functionalities you’re currently using exist.

Counting Threads on the Process (Normal)

The first method to determine the thread count of your application is to use the Process class. You can find the Process class under the System. Diagnostics namespace and the type encapsulates several valuable properties such as MachineName, ProcessInfo, ProcessId, ProcessName, and Threads.

To get the current number of threads in your .NET Process, you’ll need the following line of C#.

var numberOfThreads = Process.GetCurrentProcess().Threads.Count;

Note that this thread count is all the available threads your process has access to, including managed and unmanaged threads. Those threads could also be located on a remote machine if your process is remote.

Sadly, there is no current support for the Process type in a WASM runtime environment, and you will get the following PlatformNotSupportedException.

System.PlatformNotSupportedException: System.Diagnostics.Process is not supported on this platform.
   at System.Diagnostics.Process.GetCurrentProcess()
   at Program.<Main>$(String[] args)

Luckily, there is another approach, but you’ll need to be aware of its limitations.

Counting Threads on the Process (WASM)

Since WASM apps run in a sandbox, accessing the host system is not allowed and ultimately doesn’t work like you’d expect a process running on an OS to function. Luckily, there’s the ThreadPool class found in the System.Threading namespace, and you can ask it how many threads are currently available.

Provides a pool of threads that can be used to execute tasks, post work items, process asynchronous I/O, wait on behalf of other threads, and process timers. –Microsoft Documentation

The ThreadPool allows you to retrieve the count of all managed threads, unlike the Process class, which is a mix of managed and unmanaged threads.

var numberOfThreads = ThreadPool.ThreadCount;

Getting Thread Counts in Two Environments

Let’s run the following app as a native OS app on macOS and as a WASM-targeted app and see our results.

using System.Diagnostics;

int numberOfThreads;
try
{
    // this will fail in WASM because its not supported
    numberOfThreads = Process.GetCurrentProcess().Threads.Count;
}
catch
{
    numberOfThreads = 1;
}

Console.WriteLine($"Current number of process threads are {numberOfThreads}");
Console.WriteLine($"Current threads in thread pool are {ThreadPool.ThreadCount}");

First up is the app running natively on macOS. Your thread count may differ on machine specifications and app settings.

Current number of process threads are 11
Current threads in thread pool are 3

Let’s run the same process under the Wasmtime runtime.

➜ wasmtime HelloWasm/bin/Debug/net7.0/HelloWasm.wasm --wasm-features all
Current number of threads are 1
Current max thread in thread pool are 1

Note the difference in threads. Cool!

Conclusion

So why would you want to know how many threads your application can access? Well, in my case, I found that my WASM application was dead-locking on some trivial threading code. As I’m learning about WASM-targeted apps, I thought it would be interesting to confirm my suspicion, and after reading about WASM, I confirmed it even further. Wasmtime has experimental multithreading support, but the .NET WASM target also needs to support it to see the benefit of those additional threads. Anyways, I hope you enjoyed this post, and if you have any other ways to count the current threads in your .NET application, please let me know on Twitter at @buhakmeh.