Can anyone help transform/provide a skeleton of how to transform the below code to both functions being running concurrently, both with their own separate timers.
public void Controller()
{
List<int> totRand = new List<int>();
do
{
Thread.Sleep(new TimeSpan(0,0,0,1));
totRand.Add(ActionA());
} while (true);
do
{
Thread.Sleep(new TimeSpan(0,0,0,30));
ActionB(totRand);
totRand = new List<int>();
} while (true);
}
public int ActionA()
{
Random r = new Random();
return r.Next();
}
public void ActionB(List<int> totRand)
{
int total = 0;
//total = add up all int's in totRand
Console.WriteLine(total / totRand.Count());
}
Obviously the above would never work, but the principal is that one method runs every 1 second, adds some data to a list.
Another action also runs on a timer and takes anything that may be in this list and does something with it, then clears the list. (not worrying about the contents of the list changing whilst i'm doing this). I've read plently of tutorials and examples but quite simply can't get my head round how i'd go about this. Any ideas/hints?
To run two actions concurrently on interval you can use System.Threading.Timer
private readonly Timer _timerA;
private readonly Timer _timerB;
// this is used to protect fields that you will access from your ActionA and ActionB
private readonly Object _sharedStateGuard = new Object();
private readonly List<int> _totRand = new List<int>();
public void Controller() {
_timerA = new Timer(ActionA, null, TimeSpan.Zero, TimeSpan.FromSeconds(30));
_timerB = new Timer(ActionB, null, TimeSpan.Zero, TimeSpan.FromSeconds(1));
}
private void ActionA(object param) {
// IMPORTANT: wrap every call that uses shared state in this lock
lock(_sharedStateGuard) {
// do something with 'totRand' list here
}
}
private void ActionB(object param) {
// IMPORTANT: wrap every call that uses shared state in this lock
lock(_sharedStateGuard) {
// do something with 'totRand' list here
}
}
Shared state, in the context of your question, would be the list you want to manipulate in both actions: totRand.
Related
I need a thread safe cache to store the instances of a disposable class.
It will be used with .NET 4.0
Cache should be aware of if a stored instance is beign used or not.
When an instance is wanted from the cache, it should look at the stored avaliable instances and give one; if there is no available, create a new instance and store it.
If the cache has not been used for a period of time, cache should dispose the stored, not being used insances and clear them.
This is the solution I wrote:
private class cache<T> where T : IDisposable
{
Func<T> _createFunc;
long livingTicks;
int livingMillisecs;
public cache(Func<T> createFunc, int livingTimeInSec)
{
this.livingTicks = livingTimeInSec * 10000000;
this.livingMillisecs = livingTimeInSec * 1000;
this._createFunc = createFunc;
}
Stack<T> st = new Stack<T>();
public IDisposable BeginUseBlock(out T item)
{
this.actionOccured();
if (st.Count == 0)
item = _createFunc();
else
lock (st)
if (st.Count == 0)
item = _createFunc();
else
item = st.Pop();
return new blockDisposer(this, item);
}
long _lastTicks;
bool _called;
private void actionOccured()
{
if (!_called)
lock (st)
if (!_called)
{
_called = true;
System.Threading.Timer timer = null;
timer = new System.Threading.Timer((obj) =>
{
if ((DateTime.UtcNow.Ticks - _lastTicks) > livingTicks)
{
timer.Dispose();
this.free();
}
},
null, livingMillisecs, livingMillisecs);
}
_lastTicks = DateTime.UtcNow.Ticks;
}
private void free()
{
lock (st)
{
while (st.Count > 0)
st.Pop().Dispose();
_called = false;
}
}
private class blockDisposer : IDisposable
{
T _item;
cache<T> _c;
public blockDisposer(cache<T> c, T item)
{
this._c = c;
this._item = item;
}
public void Dispose()
{
this._c.actionOccured();
lock (this._c.st)
this._c.st.Push(_item);
}
}
}
This is a sample use:
class MyClass:IDisposable
{
public MyClass()
{
//expensive work
}
public void Dispose()
{
//free
}
public void DoSomething(int i)
{
}
}
private static Lazy<cache<MyClass>> myCache = new Lazy<cache<MyClass>>(() => new cache<MyClass>(() => new MyClass(), 60), true);//free 60sec. after last call
private static void test()
{
Parallel.For(0, 100000, (i) =>
{
MyClass cl;
using (myCache.Value.BeginUseBlock(out cl))
cl.DoSomething(i);
});
}
My questions:
Is there a faster way of doing this? (I've searched for the MemoryCache examples, but couln't figure out how I could use it for my requirements. And it requires a key check. Stack.Pop would be faster than a key search, I thought; and for my problem, performance is very important.)
In order to dispose the instances after a while (60sec. for the example code) I had to use a Timer. I just need a delayed function call that would be re-delayed on each action happening with the cache. Is there a way to do that without using a timer?
Edit:
I've tried #mjwills's comment. The performance is better with this:
ConcurrentStack<T> st = new ConcurrentStack<T>();
public IDisposable BeginUseBlock(out T item)
{
this.actionOccured();
if (!st.TryPop(out item))
item = _createFunc();
return new blockDisposer(this, item);
}
Edit2:
In my cas its not required, but if we need to control the size of the stack and dispose the unused objects, using a separate counter which will be increment-decremented with Interlocked.Increment will be faster (#mjwills)
I launch a timer with a callback function. But in this callback function I change/initialize a static object which is used after the launch of timer.
public class TimerExecute
{
// Assume that the "Dog" class exist with attribute Name initialized in the constructor
public static List<Dog> listDog = new List<Dog>();
public void callbackFunct(String param) {
// code...
listDog.Add(new Dog("Bob"));
// code...
}
public void Main() {
// add dogs Bob each 10sec
Timer addbobs = new Timer((e) => callbackFunct("arg"), null, 0, 10000);
// return argumentoutofrange exception
Console.WriteLine(listDog[0].name);
}
}
When I use the static var, I have an Exception “argument out of range exception”. I think the problem is that callback function doesn’t finished her execution and the object is not yet initialize.
I tried this solution but this doesn't work :
// add dogs Bob each 10sec
Timer addbobs = new Timer((e) => callbackFunct("arg"), null, 0, 10000);
WaitHandle h = new AutoResetEvent(false);
addbobs.Dispose(h);
Console.WriteLine(listDog[0].name);
But with this, it works :
Timer addbobs = new Timer((e) => callbackFunct("arg"), null, 0, 10000);
Thread.Sleep(2000);
Console.WriteLine(listDog[0].name);
I want that my callback function finishes her execution before the next statement.
Do you have a solution for my problem ?
Last Edit : Yes I want to be able to pass parameters to callbackFunct
Here is what I came up with. The trick is to pass in the AutoResetEvent, and you have to call Set() on that event yourself which is what signals that the method is "completed" (really it just signals that the method was called whether the method is done or not). Because it appears you need other parameters sent to the call back in addition to the WaitHandle, I made a class to encapsulate both.
public void callbackFunct(object state)
{
var myParams = (CustomParametersWithWaitHandle)state;
string name = myParams.Parameter1;
AutoResetEvent wh = myParams.WaitHandle;
// code...
listDog.Add(new Dog(name));
// code...
wh.Set(); // signal that this callback is done
}
public void Main()
{
// add dogs Bob each 10sec
AutoResetEvent wh = new AutoResetEvent(false);
var myCustomParams = new CustomParametersWithWaitHandle(wh, "bob", 314);
Timer addbobs = new Timer(new TimerCallback(callbackFunct), myCustomParams, 0, 10000);
wh.WaitOne(); // blocks here until `Set()` is called on the AutoResetEvent
Console.WriteLine(listDog[0].name);
}
}
public class CustomParametersWithWaitHandle
{
public AutoResetEvent WaitHandle { get; set; }
public string Parameter1 { get; set; }
public int Parameter2 { get; set; }
public CustomParametersWithWaitHandle(AutoResetEvent h, string parameter1, int parameter2)
{
WaitHandle = h;
Parameter1 = parameter1;
Parameter2 = parameter2;
}
I'm quite sure you should be initializing your TimerCallback with new TimerCallback(callbackFunct) instead of only the name of the function. That should be the reason your list is not being filled with Bobs (I can't seem to understand how it even compiles but...). Like:
Timer addbobs = new Timer(new TimerCallback(callbackFunct), null, 0, 10000);
The your function shall look like this:
public void callbackFunct(object state){
//...
listDog.Add(new Dog("Bob"));
//...
}
It might be possible to initialize it without a new instance, but I'm not quite sure...
P.S.: I suspect that's not the code you're using, since it doesn't even compile. Take care to update it...
I have a c# console, that I have made into a Windows service, which I would like to run reliably and constantly.
I want to prevent overlap of the same timer firing again
I want to prevent different timers trying to use the same resource at once
I want to be able to monitor the timers and interact with then.
It has a few aspects to it. Each runs very regularly. I have previously read about TaskScheduler vs Windows Service running this kind of thing, and have opted for this approach because something is running almost constantly.
TaskType1
TaskType2
TaskType3
TaskType4
I'm using timer callbacks, each with their own, similar to this simplified version:
class Program
{
static PollingService _service;
static void Main()
{
_service = new PollingService();
TimerCallback tc1 = _service.TaskType1;
TimerCallback tc2 = _service.TaskType2;
TimerCallback tc3 = _service.TaskType3A;
TimerCallback tc4 = _service.TaskType3B;
Timer t1 = new Timer(tc1, null, 1000, 5000);
Timer t2 = new Timer(tc2, null, 2000, 8000);
Timer t3 = new Timer(tc3, null, 3000, 11000);
Timer t4 = new Timer(tc4, null, 4000, 13000);
Console.WriteLine("Press Q to quit");
while (Console.ReadKey(true).KeyChar != 'q')
{
}
}
}
class PollingService
{
public void TaskType1(object state)
{
for (int i = 1; i <= 10; i++)
{
Console.WriteLine($"TaskOne numbering {i}");
Thread.Sleep(100);
}
}
public void TaskType2(object state)
{
for (int i = 10; i <= 100; i++)
{
Console.WriteLine($"TaskTwo numbering {i}");
Thread.Sleep(100);
}
}
public void TaskType3A(object state)
{
Increment(200000000);
}
public void TaskType3B(object state)
{
Increment(40000);
}
private void Increment(int startNumber)
{
for (int i = startNumber; i <= startNumber + 1000; i++)
{
Console.WriteLine($"Private {startNumber} numbering {i}");
Thread.Sleep(5);
}
}
}
1 Firstly I want to ensure these don't get tied up with each other when one sometimes runs long.
Eg. If Task one takes 20 seconds to run sometimes, I want to prevent a duplicate timer while the previous might still be running, the same for all of the timers infact. Eg. if t2 is running for a little longer than usual then don't start another. I've read a little about if (Monitor.TryEnter(lockObject)), is that the best way to handle that requirement?
2 Secondly if they both access the same resource (in my case an EF context), such that t3 is already using it, and t4 tries to do so. Is there a way of asking the timer to wait until the other finishes?
3 Lastly is there a way I can monitor these timer/callbacks? I'd like to provide an UI to see the state of this when I have it running as a windows service. My endgame there is to provide a UI that users can see if a task is running, and if not then trigger it on demand if one isn't set to run for a little while. But in the same breath, not create a duplicate while one is running.
I have wondered whether I should've asked these as separate questions, but they seem so entwined with the decision of each other.
If you have to make sure that each thread doesn't have any overlap, you can use the Timer.Change(int, int) method to stop executing at the start of the callback, and then resume it at the end of the callback. You can also do some magic with a ManualResetEvent for each thread but it'll get messy.
I'm not a fan of timers for threading and try to avoid them whenever I can. If you can sacrifice the "each thread must run after n seconds", do it. Use tasks with a cancellation token instead, it will solve your overlap problem. For example:
A.
public class Foo
{
private CancellationTokenSource _cts;
//In case you care about what tasks you have.
private List< Task > _tasks;
public Foo()
{
this._cts = new CancellationTokenSource();
this._tasks.Add(Task.Factory.StartNew(this.Method1, this._cts.Token));
this._tasks.Add(Task.Factory.StartNew(this.Method2, this._cts.Token));
this._tasks.Add(Task.Factory.StartNew(this.Method3, this._cts.Token));
this._tasks.Add(Task.Factory.StartNew(this.Method4, this._cts.Token));
}
private void Method1(object state)
{
var token = (CancellationToken) state;
while ( !token.IsCancellationRequested )
{
//do stuff
}
}
private void Method2(object state)
{
var token = (CancellationToken)state;
while (!token.IsCancellationRequested)
{
//do stuff
}
}
private void Method3(object state)
{
var token = (CancellationToken)state;
while (!token.IsCancellationRequested)
{
//do stuff
}
}
private void Method4(object state)
{
var token = (CancellationToken)state;
while (!token.IsCancellationRequested)
{
//do stuff
}
}
public void StopExecution()
{
this._cts.Cancel();
}
}
An EF context will throw an exception if used by more than one thread at a time. There is a way to synchronize it, using lock. It would look something like this, given the example above:
B.
public class Foo
{
private object _efLock;
public Foo()
{
this._efLock = new object();
}
.
.
.
private void MethodX(object state)
{
var token = (CancellationToken)state;
while (!token.IsCancellationRequested)
{
lock(this._efLock)
{
using(.......
}
}
}
}
You'll have to do that in each thread that accesses your EF context. Keep in mind that, again, maintenance gets annoying because of the cognitive load that goes with complex lock scenarios.
I recently developed an application in which I needed multiple threads to access the same EF context. As I mentioned above, the locking got to be too much (and there was a performance requirement), so I devised a solution where each thread adds its object to a common queue, and a separate thread does nothing but pull data from the queue and call into EF. That way the EF context is only ever accessed by one thread. Problem solved. Here is what that would look like given the sample above:
C.
public class Foo
{
private struct InternalEFData
{
public int SomeProperty;
}
private CancellationTokenSource _dataCreatorCts;
private CancellationTokenSource _efCts;
//In case you care about what tasks you have.
private List< Task > _tasks;
private Task _entityFrameworkTask;
private ConcurrentBag< InternalEFData > _efData;
public Foo()
{
this._efData = new ConcurrentBag< InternalEFData >();
this._dataCreatorCts = new CancellationTokenSource();
this._efCts = new CancellationTokenSource();
this._entityFrameworkTask = Task.Factory.StartNew(this.ProcessEFData, this._efCts.Token);
this._tasks.Add(Task.Factory.StartNew(this.Method1, this._dataCreatorCts.Token));
this._tasks.Add(Task.Factory.StartNew(this.Method2, this._dataCreatorCts.Token));
.
.
.
}
private void ProcessEFData(object state)
{
var token = (CancellationToken) state;
while ( !token.IsCancellationRequested )
{
InternalEFData item;
if (this._efData.TryTake(out item))
{
using ( var efContext = new MyDbContext() )
{
//Do processing.
}
}
}
}
private void Method1(object state)
{
var token = (CancellationToken) state;
while ( !token.IsCancellationRequested )
{
//Get data from whatever source
this._efData.Add(new InternalEFData());
}
}
private void Method2(object state)
{
var token = (CancellationToken) state;
while ( !token.IsCancellationRequested )
{
//Get data from whatever source
this._efData.Add(new InternalEFData());
}
}
public void StopExecution()
{
this._dataCreatorCts.Cancel();
this._efCts.Cancel();
}
}
When it comes to reading data from executing threads, I generally use a SynchronizationContext. I don't know if it's the right object to use and someone else can probably comment on that. Create a Synchronization object, pass it to your threads and have them update it with the necessary data and post it to your UI/Console thread:
D.
public struct SyncObject
{
public int SomeField;
}
public delegate void SyncHandler(SyncObject s);
public class Synchronizer
{
public event SyncHandler OnSynchronization;
private SynchronizationContext _context;
public Synchronizer()
{
this._context = new SynchronizationContext();
}
public void PostUpdate(SyncObject o)
{
var handleNullRefs = this.OnSynchronization;
if ( handleNullRefs != null )
{
this._context.Post(state => handleNullRefs((SyncObject)state), o);
}
}
}
public class Foo
{
private Synchronizer _sync;
public Foo(Synchronizer s)
{
this._sync = s;
}
private void Method1(object state)
{
var token = (CancellationToken) state;
while ( !token.IsCancellationRequested )
{
//do things
this._sync.PostUpdate(new SyncObject());
}
}
}
Again, that's how I do it, I don't know if it's the proper way.
basically, yes, or AutoResetEvent
you can stop it, wait for the resource to free up, and then restart it
keep a list of states associated with your timers, and update those states from the timers (set to running when starting, set to waiting when done, or something along these lines)
1: Likely the best is not to do anything in the timers but stat a task - IF any WHEN a flag is set or not set. Look for interlocked (the class) on how to implement that without locking.
2: Monitor. But seriously, why do they share an EF contect?
3: Sure. Create performance counters. Monitor them. The API is in windows for many many years.
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.
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.