I'm writing a C# Blazor MAUI app and am trying to perform some automated background tasks. Every 30 seconds, my applications scans the configuration to perform a connection test on a set of user-defined servers.
public static bool CanConnect(string host, int port, TimeSpan timeout) {
try {
using (var client = new TcpClient()) {
var result = client.BeginConnect(host, port, null, null);
var success = result.AsyncWaitHandle.WaitOne(timeout);
client.EndConnect(result);
System.Diagnostics.Debug.Print($"Success! {host}:{port}");
return success;
}
} catch {
System.Diagnostics.Debug.Print($"Failed connecting to {host}:{port}");
return false;
}
}
When my scheduler begins queuing up these tasks, I notice a very slight (but noticeable) hiccup on the GUI.
clusters.AsParallel()
.ForAll(item => item.Status = ClusterIsAccessible(item) ? Cluster.ConnectionStatus.Online : Cluster.ConnectionStatus.Offline);
I believe the hiccup is a result of threads being created. I am noticing that when the jobs complete, the threads that are used to scan the connections will exit / timeout after 20-25s.
The thread 0x225c has exited with code 0 (0x0).
The thread 0x4d2c has exited with code 0 (0x0).
The thread 0x7c28 has exited with code 0 (0x0).
The thread 0x6724 has exited with code 0 (0x0).
The thread 0x822c has exited with code 0 (0x0).
The thread 0x849c has exited with code 0 (0x0).
The thread 0x5a24 has exited with code 0 (0x0).
The thread 0x86ac has exited with code 0 (0x0).
The thread 0x8840 has exited with code 0 (0x0).
The thread 0x22f8 has exited with code 0 (0x0).
The thread 0x74e0 has exited with code 0 (0x0).
The thread 0x7550 has exited with code 0 (0x0).
The thread 0x8b80 has exited with code 0 (0x0).
The thread 0x4d48 has exited with code 0 (0x0).
The thread 0x14a8 has exited with code 0 (0x0).
The thread 0x5ed0 has exited with code 0 (0x0).
My thought was that LINQ isn't using a thread pool but rather initializing new threads for each task.
To try and force the jobs onto the existing C# thread pool, I rewrote the iteration logic to use ThreadPool::QueueUserWorkItem(...) but this also resulted in threads exiting and a slight hiccup when threads were being created.
clusters.ForEach((item) => ThreadPool.QueueUserWorkItem(state => {
item.Status = ClusterIsAccessible(item) ? Cluster.ConnectionStatus.Online : Cluster.ConnectionStatus.Offline;
}));
What am I doing wrong? I don't want to create unnecessary threads when there are already threads waiting for work.