Mutithreading with sequence - c#

I have a main task that is spawning threads to do some work. When the work is completed it will write to the console.
My problem is that some of the threads that are created later will finish faster than those created earlier. However I need the writing to the console to be done in the same exact sequence as the thread was created.
So if a thread had completed its task, while some earlier threads had not, it has to wait till those earlier threads complete too.
public class DoRead
{
public DoRead()
{
}
private void StartReading()
{
int i = 1;
while (i < 10000)
{
Runner r = new Runner(i, "Work" + i.ToString());
r.StartThread();
i += 1;
}
}
}
internal class Runner : System.IDisposable
{
int _count;
string _work = "";
public Runner(int Count, string Work)
{
_count = Count;
_work = Work;
}
public void StartThread()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(runThreadInPool), this);
}
public static void runThreadInPool(object obj)
{
((Runner)obj).run();
}
public void run()
{
try
{
Random r = new Random();
int num = r.Next(1000, 2000);
DateTime end = DateTime.Now.AddMilliseconds(num);
while (end > DateTime.Now)
{
}
Console.WriteLine(_count.ToString() + " : Done!");
}
catch
{
}
finally
{
_work = null;
}
}
public void Dispose()
{
this._work = null;
}
}

There may be a simpler way to do this than I used, (I'm used to .Net 4.0).
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ConsoleApplication5
{
class Program
{
public static readonly int numOfTasks = 100;
public static int numTasksLeft = numOfTasks;
public static readonly object TaskDecrementLock = new object();
static void Main(string[] args)
{
DoRead dr = new DoRead();
dr.StartReading();
int tmpNumTasks = numTasksLeft;
while ( tmpNumTasks > 0 )
{
Thread.Sleep(1000);
tmpNumTasks = numTasksLeft;
}
List<string> strings = new List<string>();
lock( DoRead.locker )
{
for (int i = 1; i <= Program.numOfTasks; i++)
{
strings.Add( DoRead.dicto[i] );
}
}
foreach (string s in strings)
{
Console.WriteLine(s);
}
Console.ReadLine();
}
public class DoRead
{
public static readonly object locker = new object();
public static Dictionary<int, string> dicto = new Dictionary<int, string>();
public DoRead()
{
}
public void StartReading()
{
int i = 1;
while (i <= Program.numOfTasks )
{
Runner r = new Runner(i, "Work" + i.ToString());
r.StartThread();
i += 1;
}
}
}
internal class Runner : System.IDisposable
{
int _count;
string _work = "";
public Runner(int Count, string Work)
{
_count = Count;
_work = Work;
}
public void StartThread()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(runThreadInPool), this);
}
public static void runThreadInPool(object obj)
{
Runner theRunner = ((Runner)obj);
string theString = theRunner.run();
lock (DoRead.locker)
{
DoRead.dicto.Add( theRunner._count, theString);
}
lock (Program.TaskDecrementLock)
{
Program.numTasksLeft--;
}
}
public string run()
{
try
{
Random r = new Random();
int num = r.Next(1000, 2000);
Thread.Sleep(num);
string theString = _count.ToString() + " : Done!";
return theString;
}
catch
{
}
finally
{
_work = null;
}
return "";
}
public void Dispose()
{
this._work = null;
}
}
}
}
Basically, I store the string you want printed from each task into a dictionary where the index is the task#. (I use a lock to make accessing the dictionary safe).
Next, so that the main program waits until all the background threads are done, I used another locked access to a NumTasksLeft variable.
I added stuff into the callback for the Runner.
It is bad practice to use busy loops, so I changed it to a Thread.Sleep( num ) statement.
Just change numOfTasks to 10000 to match your example.
I pull the return strings out of the dictionary in order, and then print it to the screen.
I'm sure you could refactor this to move or otherwise deal with the global variables, but this works.
Also, you might have noticed I didn't use the lock in the command
tmpNumTasks = numTasksLeft;
That's threadsafe, since numTasksLeft is an int which is read atomically on 32-bit computers and higher.

I don't know much on C#, but the whole idea of multi-threading is that you have multiple thread executing independently and you can never know which one will finish earlier (and you shouldn't expect earlier thread to end earlier).
One workaround is, instead writing out the finish message in the processing thread, have the processing thread setup a flag somewhere (probably a list with no of elements = no of thread spawned), and have a separate thread print out the finish message base on the flags in that list, and report up to the position that previous flag is consecutively "finished".
Honestly I don't feel that reasonable for you to print finish message like this anyway. I think changing the design is way better to have such meaningless "feature".

Typically, such requirements are met with an incrementing sequence number, much as you have already done.
Usually, the output from the processing threads is fed through a filter object that contains a list, (or dictionary), of all out-of-order result objects, 'holding them back' until all results with a lower seqeuence-number have come in. Again, similar to what you have already done.
What is not necessary is any kind of sleep() loop. The work threads themselves can operate the filter object, (which would beed a lock), or the work threads can producer-consumer-queue the results to an 'output thread' that operates the out-of-order filter.
This scheme works fine with pooled work threads, ie. those without continual create/terminate/destroy overhead.

Related

Thread executes "slowly"

I am starting with threads and wrote for the sake of learning the following simple program, which later would be used to calculate about 100,000 times a formula (it is a relatively simple one but which takes an iterated range of values).
The problem with it is that I expected every thread to execute in almost no time and thus the complete program to finish nearly immediately, but the fact is that everything runs too slow (about 10s)...
static readonly double TotalIterations = 1000;
public static Iterations ActualIterations = new Iterations();
public static void Main()
{
var par1 = "foo";
var par2 = "boo";
var par3 = 3;
for (int i = 0; i < TotalIterations; i++)
{
new Thread(() => new Calculations().Calculate(par1, par2, par3)).Start();
}
AwaitingThreads();
}
static void AwaitThreads()
{
Console.WriteLine("Awaiting threads to finished...");
while (true)
{
lock (ActualIterations)
{
if (ActualIterations.Progress() == TotalIterations) break;
}
Thread.Sleep(1 * 1000);
}
Console.WriteLine("All threads finished!");
}
public class Calculations {
public bool Calculate(string par1, string par2, int par3)
{
// ...
bool result = false;
lock (ActualIterations)
{
ActualIterations.Incr();
}
return result;
}
}
public class Iterations
{
int progress = 0;
public void Incr()
{
progress++;
}
public int Progress()
{
return progress;
}
}
I also tried using a ThreadPool like this, but there was no improvement...
static readonly double TotalIterations = 1000;
static string par1 = "foo";
static string par2 = "boo";
static int par3 = 3;
public static Iterations ActualIterations = new Iterations();
public static void Main()
{
ThreadPool.QueueUserWorkItem(MyThreadPool);
AwaitThreads();
}
static void AwaitThreads()
{
Console.WriteLine("Awaiting threads to finished...");
while (true)
{
lock (ActualIterations)
{
if (ActualIterations.Progress() == TotalIterations) break;
}
Thread.Sleep(1 * 1000);
}
Console.WriteLine("All threads finished!");
}
static void MyThreadPool(Object stateInfo)
{
for (int i = 0; i < TotalIterations; i++)
{
new Thread(() => new Calculations().Calculate(par1, par2, par3)).Start();
}
}
public class Calculations {
public bool Calculate(string par1, string par2, int par3)
{
// ...
bool result = false;
lock (ActualIterations)
{
ActualIterations.Incr();
}
return result;
}
}
public class Iterations
{
int progress = 0;
public void Incr()
{
progress++;
}
public int Progress()
{
return progress;
}
}
When I quit using threads in this example and use a static method, executing it sequentially in my for loop, the program finishes in 1s...
Can anybody enlighten me what I am doing wrong here with those threads?
The problem with it is that I expected every thread to execute in almost no time
Right. You're ignoring the fact that creating a new thread is a relatively expensive operation. Far, far more expensive than "acquiring a lock and incrementing an integer" which is the work you're doing in the thread.
To give a real world comparison, it's a little like ordering a new car, waiting it to be delivered, and then driving it 1km. That's going to be slower than just walking 1km.
Using the thread pool would be faster, but you're not using it correctly - you're launching one thread pool task which then creates all the other threads again.
I would encourage you to look at using Task<T> instead, which normally uses the thread pool under the hood, and is a generally more modern abstraction for this sort of work.
This is the way to proceed doing what you wanted to do:
class Program
{
static void Main(string[] args)
{
List<Task> tasks = new List<Task>();
for (int i = 0; i < 1000; i++)
{
tasks.Add(Task.Run(() =>
{
Console.WriteLine("Calculations " + DateTime.Now);
}));
}
Task.WaitAll(tasks.ToArray());
}
}
Tasks are actually optimized and programmer-friendly to use if you need to work with threads.
Another advice i want to give you is to create an Object just for locking purposes, example:
class Program
{
private static Object _locker = new Object();
static void Main(string[] args)
{
List<Task> tasks = new List<Task>();
for (int i = 0; i < 1000; i++)
{
tasks.Add(Task.Run(() =>
{
lock (_locker)
{
Console.WriteLine("Calculations " + DateTime.Now);
}
}));
}
Task.WaitAll(tasks.ToArray());
}
}
I see the problem in the AwaitThreads method.
It uses the same lock (ActualIterations) as working thread and it makes working threads to wait for shared resource additionally.
Also (as it was mentioned by #Euphoric) the thread working code you have shown is just about single increment and it uses the shared resource between all threads.
You have to change it in some another way and try to avoid shared resource usage in multi threaded environment.
For example, if you need to make some calculation on huge data array you have to feed each thread own data part to be processed and then wait for all tasks to be finished. There is Task concept and Task.WaitAll

how to make Wait until all threads finished it's work from threadpool in c#

for (int task = 0; task < 20; task++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(TaskCallBack), new object[] { filepath1, filepath2,
filepath3 });
}
public static void TaskCallBack(object state)
{
object[] array = state as object[];
string filea = Convert.ToString(array[0]);
string fileb = Convert.ToString(array[1]);
string filec = Convert.ToString(array[2]);
//something below
}
I want main thread to be waited until all threads finishes its work. Please help
The best way to handle this would be to use Task.Run() and Task.WhenAll(), or to use Parallel.Invoke().
However, if you need to use ThreadPool.QueueUserWorkItem you can solve this issue as follows:
For ease of use, encapsulate all the data that you want to pass to the thread in a class. This data should include an instance of CountdownEvent initialised with a count equal to the number of threads you want to wait for. (In the sample code below, this class is called ThreadData.)
Inside your TaskCallBack() methods, call CountdownEvent.Signal() when the method has completed.
Inside the main thread, start all the threadpool threads and then call CountdownEvent.Wait() to wait for all the threads to complete.
Putting this all together in a compilable console app:
using System;
using System.Threading;
namespace CoreConsole
{
public sealed class ThreadData
{
public ThreadData(CountdownEvent countdown, int index)
{
Countdown = countdown;
Index = index;
}
public CountdownEvent Countdown { get; }
public int Index { get; }
}
public static class Program
{
static void Main()
{
int n = 20;
var countdown = new CountdownEvent(n);
for (int task = 0; task < n; task++)
{
ThreadPool.QueueUserWorkItem(TaskCallBack, new ThreadData(countdown, task));
}
Console.WriteLine("Waiting for all threads to exit");
countdown.Wait();
Console.WriteLine("Waited for all threads to exit");
}
public static void TaskCallBack(object state)
{
var data = (ThreadData) state;
Console.WriteLine($"Thread {data.Index} is starting.");
Thread.Sleep(_rng.Next(2000, 10000));
data.Countdown.Signal();
Console.WriteLine($"Thread {data.Index} has finished.");
}
static readonly Random _rng = new Random(45698);
}
}
The ThreadData.Index property is just used to identify each thread in the Console.WriteLine() calls.
Note: In real code, it is important to always signal the Countdown event, even if the thread throws an exception - so you should wrap the code in a try/finally like so:
public static void TaskCallBack(object state)
{
var data = (ThreadData)state;
try
{
// Do work here.
Console.WriteLine($"Thread {data.Index} is starting.");
Thread.Sleep(_rng.Next(2000, 10000));
Console.WriteLine($"Thread {data.Index} has finished.");
}
finally
{
data.Countdown.Signal();
}
}
Like #Ackdari mentioned in his comment, you could use Task.Run. But you don't need the await keyword. Just create a collection with the tasks and wait for it.
Example:
// Create a list that will hold the tasks
List<Task> tasks = new List<Task>;
// Create the tasks
for (int taskId = 0; taskId < 20; task++)
{
tasks.Add(Task.Run(() => { TaskCallBack(new object[] { filepath1, filepath2, filepath3 }); }));
}
// Wait for ALL tasks to complete
Task.WaitAll(tasks.ToArray());
That way you could also use your own method that will be run by the task.
Example:
public static void ReplaceWithABetterName(string[] filePaths)
{
string filea = filePaths[0);
string fileb = filePaths[1];
string filec = filePaths[2];
//do stuff
}

Read-write synchronization class implementation

I am writing a read-write synchronization class, and would like some advice on what I to do next. For some reason, it sometimes allows a Read to happen in the middle of a Write, and I cannot find the reason.
This is what I want from this class:
Reads not allowed at the same time as writes.
Multiples reads can happen at the same time.
Only one write can happen at a time.
When a write is needed, all already executing reads continue,
no new reads are allowed, when all reads finish the write executes.
I know that .Net framework has a class to do this... but what I want is to understand and to reproduce something like that. I'm not reinventing the wheel, I am trying to understand it by making my own wheel... happens that my wheel is kinda squared a bit.
What I have currently is this:
public class ReadWriteSync
{
private ManualResetEvent read = new ManualResetEvent(true);
private volatile int readingBlocks = 0;
private AutoResetEvent write = new AutoResetEvent(true);
private object locker = new object();
public IDisposable ReadLock()
{
lock (this.locker)
{
this.write.Reset();
Interlocked.Increment(ref this.readingBlocks);
this.read.WaitOne();
}
return new Disposer(() =>
{
if (Interlocked.Decrement(ref this.readingBlocks) == 0)
this.write.Set();
});
}
public IDisposable WriteLock()
{
lock (this.locker)
{
this.read.Reset();
this.write.WaitOne();
}
return new Disposer(() =>
{
this.read.Set();
if (this.readingBlocks == 0)
this.write.Set();
});
}
class Disposer : IDisposable
{
Action disposer;
public Disposer(Action disposer) { this.disposer = disposer; }
public void Dispose() { this.disposer(); }
}
}
This is my test program... when something goes wrong it prints the lines in red.
class Program
{
static ReadWriteSync sync = new ReadWriteSync();
static void Main(string[] args)
{
Console.BackgroundColor = ConsoleColor.DarkGray;
Console.ForegroundColor = ConsoleColor.Gray;
Console.Clear();
Task readTask1 = new Task(() => DoReads("A", 20));
Task readTask2 = new Task(() => DoReads("B", 30));
Task readTask3 = new Task(() => DoReads("C", 40));
Task readTask4 = new Task(() => DoReads("D", 50));
Task writeTask1 = new Task(() => DoWrites("E", 500));
Task writeTask2 = new Task(() => DoWrites("F", 200));
readTask1.Start();
readTask2.Start();
readTask3.Start();
readTask4.Start();
writeTask1.Start();
writeTask2.Start();
Task.WaitAll(
readTask1, readTask2, readTask3, readTask4,
writeTask1, writeTask2);
}
static volatile bool reading;
static volatile bool writing;
static void DoWrites(string name, int interval)
{
for (int i = 1; i < int.MaxValue; i += 2)
{
using (sync.WriteLock())
{
Console.ForegroundColor = (writing || reading) ? ConsoleColor.Red : ConsoleColor.Gray;
writing = true;
Console.WriteLine("WRITE {1}-{0} BEGIN", i, name);
Thread.Sleep(interval);
Console.WriteLine("WRITE {1}-{0} END", i, name);
writing = false;
}
Thread.Sleep(interval);
}
}
static void DoReads(string name, int interval)
{
for (int i = 0; i < int.MaxValue; i += 2)
{
using (sync.ReadLock())
{
Console.ForegroundColor = (writing) ? ConsoleColor.Red : ConsoleColor.Gray;
reading = true;
Console.WriteLine("READ {1}-{0} BEGIN", i, name);
Thread.Sleep(interval * 3);
Console.WriteLine("READ {1}-{0} END", i, name);
reading = false;
}
Thread.Sleep(interval);
}
}
}
What is wrong with all this... any advice on how to do it correctly?
The primary issue that I see is that you are trying to make reset events encompass both the meanings of a read/write and the handling of their current state, without synchronizing in a consistent manner.
Here's an example of how the inconsistent synchronization may bite you in your specific code.
A write is disposing and a read is coming in.
The read acquires the lock
The write sets the read ManualResetEvent (MRE)
The write checks the current read count, finding 0
The read resets the write AutoResetEvent (ARE)
The read increments the read count
The read finds its MRE has been set and begins to read
All is fine so far, but the write hasn't finished yet...
A second write comes in and acquires the lock
The second write resets the read MRE
The first write finishes by setting the write ARE
The second write finds its ARE has been set and begins to write
When thinking about multiple threads, unless you are within a lock of some sort, you must take the view that all other data is wildly fluctuating and cannot be trusted.
A naive implementation of this may split out the queueing logic from the state logic and synchronize appropriately.
public class ReadWrite
{
private static int readerCount = 0;
private static int writerCount = 0;
private int pendingReaderCount = 0;
private int pendingWriterCount = 0;
private readonly object decision = new object();
private class WakeLock:IDisposable
{
private readonly object wakeLock;
public WakeLock(object wakeLock) { this.wakeLock = wakeLock; }
public virtual void Dispose() { lock(this.wakeLock) Monitor.PulseAll(this.wakeLock); }
}
private class ReadLock:WakeLock
{
public ReadLock(object wakeLock) : base(wakeLock) { Interlocked.Increment(ref readerCount); }
public override void Dispose()
{
Interlocked.Decrement(ref readerCount);
base.Dispose();
}
}
private class WriteLock:WakeLock
{
public WriteLock(object wakeLock) : base(wakeLock) { Interlocked.Increment(ref writerCount); }
public override void Dispose()
{
Interlocked.Decrement(ref writerCount);
base.Dispose();
}
}
public IDisposable TakeReadLock()
{
lock(decision)
{
pendingReaderCount++;
while (pendingWriterCount > 0 || Thread.VolatileRead(ref writerCount) > 0)
Monitor.Wait(decision);
pendingReaderCount--;
return new ReadLock(this.decision);
}
}
public IDisposable TakeWriteLock()
{
lock(decision)
{
pendingWriterCount++;
while (Thread.VolatileRead(ref readerCount) > 0 || Thread.VolatileRead(ref writerCount) > 0)
Monitor.Wait(decision);
pendingWriterCount--;
return new WriteLock(this.decision);
}
}
}

Is this a safe way to execute threads alternatively?

I would like to run code alternatively, so I could stop execution at any moment. Is this code safe?
static class Program
{
static void Main()
{
var foo = new Foo();
//wait for interaction (this will be GUI app, so eg. btnNext_click)
foo.Continue();
//wait again etc.
foo.Continue();
foo.Continue();
foo.Continue();
foo.Continue();
foo.Continue();
}
}
class Foo
{
public Foo()
{
new Thread(Run).Start();
}
private void Run()
{
Break();
OnRun();
}
protected virtual void OnRun()
{
for (var i = 0; i < 5; i++)
{
Console.WriteLine(i);
Break();
}
//do something else and break;
}
private void Break()
{
lock (this)
{
Monitor.Pulse(this);
Monitor.Wait(this);
}
}
public void Continue()
{
lock (this)
{
Monitor.Pulse(this);
Monitor.Wait(this);
}
}
}
Of course I know, that now the application will never ends, but that's not the point.
I need this, because I would like to present steps in some kind of an algorithm and describe what is going on in particular moment, and making everything in one thread would lead to many complications even when using small amount of loops in the code. For example those lines:
for (var i = 0; i < 5; i++)
{
Console.WriteLine(i);
Break();
}
should be then replaced with:
if (this.i < 5)
{
Console.WriteLine(i++);
}
And that is just a small example of what I want to present. The code will be more complicated than a dummy for loop.
I recommend you check out this blog post about implementing fibers.
Code (In case the site goes down.)
public class Fiber
{
private readonly Stack<IEnumerator> stackFrame = new Stack<IEnumerator>();
private IEnumerator currentRoutine;
public Fiber(IEnumerator entryPoint)
{
this.currentRoutine = entryPoint;
}
public bool Step()
{
if (currentRoutine.MoveNext())
{
var subRoutine = currentRoutine.Current
as IEnumerator;
if (subRoutine != null)
{
stackFrame.Push(currentRoutine);
currentRoutine = subRoutine;
}
}
else if (stackFrame.Count > 0)
{
currentRoutine = stackFrame.Pop();
}
else
{
OnFiberTerminated(
new FiberTerminatedEventArgs(
currentRoutine.Current
)
);
return false;
}
return true;
}
public event EventHandler<FiberTerminatedEventArgs> FiberTerminated;
private void OnFiberTerminated(FiberTerminatedEventArgs e)
{
var handler = FiberTerminated;
if (handler != null)
{
handler(this, e);
}
}
}
public class FiberTerminatedEventArgs : EventArgs
{
private readonly object result;
public FiberTerminatedEventArgs(object result)
{
this.result = result;
}
public object Result
{
get { return this.result; }
}
}
class FiberTest
{
private static IEnumerator Recurse(int n)
{
Console.WriteLine(n);
yield return n;
if (n > 0)
{
yield return Recurse(n - 1);
}
}
static void Main(string[] args)
{
var fiber = new Fiber(Recurse(5));
while (fiber.Step()) ;
}
}
"...this will be GUI app..."
Then you probably do not want and will not have sequential code like above in Main().
I.e. the main GUI thread will not execute a serial code like above, but generally be idle, repainting, etc. or handling the Continue button click.
In that event handler you may better use an Auto|ManualResetEvent to signal the worker to proceed.
In the worker, just wait for the event.
I would suggest that any time one considers using Monitor.Wait(), one should write code so that it would work correctly if the Wait sometimes spontaneously acted as though it received a pulse. Typically, this means one should use the pattern:
lock(monitorObj)
{
while(notYetReady)
Monitor.Wait(monitorObj);
}
For your scenario, I'd suggest doing something like:
lock(monitorObj)
{
turn = [[identifier for this "thread"]];
Monitor.PulseAll(monitorObj);
while(turn != [[identifier for this "thread"]])
Monitor.Wait(monitorObj);
}
It is not possible for turn to change between its being checked whether it's the current thread's turn to proceed and the Monitor.Wait. Thus, if the Wait isn't skipped, the PulseAll is guaranteed to awaken it. Note that the code would work just fine if Wait spontaneously acted as though it received a pulse--it would simply spin around, observe turn wasn't set for the current thread, and go back to waiting.

Getting list of currently active managed threads in .NET?

For a "log information for support" type of function I'd like to enumerate and dump active thread information.
I'm well aware of the fact that race conditions can make this information semi-inaccurate, but I'd like to try to get the best possible result, even if it isn't 100% accurate.
I looked at Process.Threads, but it returns ProcessThread objects, I'd like to have a collection of Thread objects, so that I can log their name, and whether they're background threads or not.
Is there such a collection available, even if it is just a snapshot of the active threads when I call it?
ie.
Thread[] activeThreads = ??
Note, to be clear, I am not asking about Process.Threads, this collection gives me a lot, but not all of what I want. I want to know how much time specific named threads in our application is currently using (which means I will have to look at connecting the two types of objects later, but the names is more important than the CPU time to begin with.)
If you're willing to replace your application's Thread creations with another wrapper class, said wrapper class can track the active and inactive Threads for you. Here's a minimal workable shell of such a wrapper:
namespace ThreadTracker
{
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
public class TrackedThread
{
private static readonly IList<Thread> threadList = new List<Thread>();
private readonly Thread thread;
private readonly ParameterizedThreadStart start1;
private readonly ThreadStart start2;
public TrackedThread(ParameterizedThreadStart start)
{
this.start1 = start;
this.thread = new Thread(this.StartThreadParameterized);
lock (threadList)
{
threadList.Add(this.thread);
}
}
public TrackedThread(ThreadStart start)
{
this.start2 = start;
this.thread = new Thread(this.StartThread);
lock (threadList)
{
threadList.Add(this.thread);
}
}
public TrackedThread(ParameterizedThreadStart start, int maxStackSize)
{
this.start1 = start;
this.thread = new Thread(this.StartThreadParameterized, maxStackSize);
lock (threadList)
{
threadList.Add(this.thread);
}
}
public TrackedThread(ThreadStart start, int maxStackSize)
{
this.start2 = start;
this.thread = new Thread(this.StartThread, maxStackSize);
lock (threadList)
{
threadList.Add(this.thread);
}
}
public static int Count
{
get
{
lock (threadList)
{
return threadList.Count;
}
}
}
public static IEnumerable<Thread> ThreadList
{
get
{
lock (threadList)
{
return new ReadOnlyCollection<Thread>(threadList);
}
}
}
// either: (a) expose the thread object itself via a property or,
// (b) expose the other Thread public methods you need to replicate.
// This example uses (a).
public Thread Thread
{
get
{
return this.thread;
}
}
private void StartThreadParameterized(object obj)
{
try
{
this.start1(obj);
}
finally
{
lock (threadList)
{
threadList.Remove(this.thread);
}
}
}
private void StartThread()
{
try
{
this.start2();
}
finally
{
lock (threadList)
{
threadList.Remove(this.thread);
}
}
}
}
}
and a quick test driver of it (note I do not iterate over the list of threads, merely get the count in the list):
namespace ThreadTracker
{
using System;
using System.Threading;
internal static class Program
{
private static void Main()
{
var thread1 = new TrackedThread(DoNothingForFiveSeconds);
var thread2 = new TrackedThread(DoNothingForTenSeconds);
var thread3 = new TrackedThread(DoNothingForSomeTime);
thread1.Thread.Start();
thread2.Thread.Start();
thread3.Thread.Start(15);
while (TrackedThread.Count > 0)
{
Console.WriteLine(TrackedThread.Count);
}
Console.ReadLine();
}
private static void DoNothingForFiveSeconds()
{
Thread.Sleep(5000);
}
private static void DoNothingForTenSeconds()
{
Thread.Sleep(10000);
}
private static void DoNothingForSomeTime(object seconds)
{
Thread.Sleep(1000 * (int)seconds);
}
}
}
Not sure if you can go such a route, but it will accomplish the goal if you're able to incorporate at an early stage of development.
Is it feasible for you to store thread information in a lookup as you create each thread in your application?
As each thread starts, you can get its ID using AppDomain.GetCurrentThreadId(). Later, you can use this to cross reference with the data returned from Process.Threads.

Categories

Resources