How to dispose thread in c# - c#

I have used threading in my web application which I have mentioned below:
var t1 = new Thread(F1);
t1.IsBackground = true;
t1.Start();
var t2 = new Thread(F2);
t2.IsBackground = true;
t2.Start();
var t3 = new Thread(F3);
t3.IsBackground = true;
t3.Start();
var t4 = new Thread(F4);
t4.IsBackground = true;
t4.Start();
t1.Join();
t2.Join();
t3.Join();
t4.Join();
This is working fine and giving me the desired output.
Do I need to kill/Dispose the thread after this, if yes then how ?
Please guide.
I have told that if I do not dispose it, it might raise performance issue.

The call to Join() is what de-allocates the thread. You don't have to do anything else. Just make sure that the threads clean up any resources they might be using before they exit.
That said, I would urge you to look into using the thread pool or the Task Parallel Library (TPL) rather than explicitly managing threads. They're easier to use, and handle this kind of thing much more smoothly.

If I were in your shoes, I'd be using a ThreadPool instead of manual threads. It handles all that stuff itself, and you don't have the overhead of creating and destroying threads. The code will probably be slightly more complex, because you'll need to use a ManualResetEvent instead of a simple Thread.Join() (see How can I accomplish ThreadPool.Join?), but you won't have to worry about creating too many threads, and it's nearly 40x faster.
Here's the class for a test I wrote comparing the two approaches:
class ThreadPoolVsThreads
{
private static readonly PerformanceMonitor threadPoolTest = new PerformanceMonitor("ThreadPoolTest");
private static readonly PerformanceMonitor threadTest = new PerformanceMonitor("ThreadTest");
private const int iterations = 100;
private const int threads = 10;
private static long somevalue;
public static void Test()
{
TestHelper.PerformTest(10, threadPoolTest, ThreadPoolTest);
TestHelper.PerformTest(10, threadTest, ThreadTest);
}
private static void ThreadPoolTest(int iteration)
{
for (int i = 0; i < iterations; i++)
{
var resetEvents = new ManualResetEvent[threads];
for (int j = 0; j < threads; j++)
{
var re = new ManualResetEvent(false);
resetEvents[j] = re;
ThreadPool.QueueUserWorkItem(o =>
{
somevalue++;
re.Set();
});
}
WaitHandle.WaitAll(resetEvents);
}
}
private static void ThreadTest(int iteration)
{
for (int i = 0; i < iterations; i++)
{
var threadArray = new Thread[threads];
for (int j = 0; j < threads; j++)
{
var thread = new Thread(o => somevalue++);
threadArray[j] = thread;
thread.Start();
}
for (int j = 0; j < threads; j++)
{
threadArray[j].Join();
}
}
}
}
And here's the output for five runs:
ThreadPoolTest action completed: iteration = 1, completionTime = 53, averageCompletionTime = 53.000
ThreadTest action completed: iteration = 1, completionTime = 2128, averageCompletionTime = 2128.000
ThreadPoolTest action completed: iteration = 2, completionTime = 42, averageCompletionTime = 47.500
ThreadTest action completed: iteration = 2, completionTime = 2149, averageCompletionTime = 2138.500
ThreadPoolTest action completed: iteration = 3, completionTime = 65, averageCompletionTime = 53.333
ThreadTest action completed: iteration = 3, completionTime = 2078, averageCompletionTime = 2118.333
ThreadPoolTest action completed: iteration = 4, completionTime = 72, averageCompletionTime = 58.000
ThreadTest action completed: iteration = 4, completionTime = 2137, averageCompletionTime = 2123.000
ThreadPoolTest action completed: iteration = 5, completionTime = 43, averageCompletionTime = 55.000
ThreadTest action completed: iteration = 5, completionTime = 2085, averageCompletionTime = 2115.400

Related

Adding System.Timer to System.Threading.RegisterWaitForSingleObject

How can I add System.Timer to System.Threading.RegisterWaitForSingleObject to run my thread after an interval time? In the code below, how do I specify the System.Timer[] timer object? Thanks.
int lvCtlrIdStart = 0;
int lvCtlrIdEnd = 0;
object s_range = null;
for (int i = 0; i < NbrOfThrds - 1; i++)
{
m_WorkerEvtThreads[i] = new ManualResetEvent(false);
int dueTime = int.Parse(lvTask.ctlrArray[i, 3].ToString());
lvCtlrIdStart = int.Parse(lvTask.ctlrArray[i, 0].ToString());
lvCtlrIdEnd = int.Parse(lvTask.ctlrArray[i, 1].ToString());
s_range = $"{lvCtlrIdStart},{lvCtlrIdEnd}";
dueTime = int.Parse(lvTask.ctlrArray[i, 3].ToString());
Action<int> m_workerThread = (sqm) =>
{
lvTask.WaitHandle = ThreadPool.RegisterWaitForSingleObject(m_SpecialWorkerEventThread,
new WaitOrTimerCallback(m_SendQueuedMsgs), s_range, 0, true);
};
timer[i].Change(dueTime, Timeout.Infinite);
}
I found a way to resolve this:
int dueTime = int.Parse(lvTask.ctlrArray[0, 3].ToString());
int lvCtlrIdStart = 0;
int lvCtlrIdEnd = 0;
object s_range = $"{lvCtlrIdStart},{lvCtlrIdEnd}";
bool bIntvlStart = false;
m_WorkerEvtThreads = new AutoResetEvent[NbrThrds]; // reset ALL events before looping into the next sets of Threadpool
CancellationTokenSource cts = new CancellationTokenSource(); // Create the token source
for (int i = 0; i < NbrThrds; i++) // Iterate based on the number of tasks to run
{
try
{
int intvlStart = 1000 * i; // delay before my callback method is invoked..
dueTime = bIntvlStart ? int.Parse(lvTask.ctlrArray[i, 3].ToString()) : intvlStart; // first loop is (1000 * loop_count) sec stagger run, otherwise kickoff on interval time
m_WorkerEvtThreads[i] = new AutoResetEvent(false); // initial each thread event
m_WorkerEvtThreads[i].Reset();
Thread.Sleep(WaitHandle.WaitTimeout); // sleep 258ms...
CurrentInstance = int.Parse(lvTask.ctlrArray[i, 2].ToString()) - 1; // get the current instance
lvCtlrIdStart = int.Parse(lvTask.ctlrArray[i, 0].ToString()); // start controller ID
lvCtlrIdEnd = int.Parse(lvTask.ctlrArray[i, 1].ToString()); // end controller ID
s_range = $"{lvCtlrIdStart},{lvCtlrIdEnd}"; // combine to pass to SendQueueMessage()
ThreadPool.QueueUserWorkItem(delegate
{ Thread.CurrentThread.Name = $"LV Instance {CurrentInstance}";
lvTask.TN = $"{Thread.CurrentThread.Name}"; // name the current instance task
m_ThreadName = $"{lvTask.TN}";
TimerSendQueueMsgCallback(s_range, intvlStart, dueTime); // Call the timer callback method
}, cts.Token); // cancellation token
}
catch (Exception ex)
{
log.WriteLineToBuf(ref logBuf, $"Exception: OnLvMessage() - {ex.Message}");
}
}
cts.Cancel(); // request cancellation...

Is System.Threading.Semaphore weak?

There are two types of Semaphore
Strong Semaphore: maintains an order internally.
Weak semaphore: which does not provide any ordered access to a critical section which can cause starvation.
“There is no guaranteed order, such as FIFO or LIFO, in which blocked threads enter the semaphore.” from MSDN remarks in System.Threading.Semaphore.
I would like to confirm what type of semaphore implementation is provided by .Net Framework ?
static int count = 0;
static Semaphore writerSem = new Semaphore(0, 10);
static void Main(string[] args)
{
Thread[] readers = new Thread[10];
for (int i = 0; i < readers.Length; i++)
{
readers[i] = new Thread(new ThreadStart(Reader));
readers[i].Name = "Reader: " + i;
readers[i].Start();
}
Thread writer = new Thread(new ThreadStart(Writer));
writer.Start();
for (int i = 0; i < readers.Length; i++)
{
readers[i].Join();
}
writer.Join();
}
static void Reader()
{
while (true)
{
writerSem.WaitOne();
Console.WriteLine(count + " " + Thread.CurrentThread.Name);
}
}
static void Writer()
{
while (true)
{
count++;
writerSem.Release(10);
Thread.Sleep(1000);
}
}
I have tested it by writing this program. It is just confirmed that System.Threading.Semaphore is implemented as Weak Semaphore.

WaitOne() waits forever even though all events fired

Threaded is suppossed to create 4 seperate threads and wait for each of them till they finish. Each thread sleeps for a while and terminates only when the shared Mutex opbject is not occupied by another thread and then signal trough a event that it finished(This is a simplified version of my code but fails at the same spot)
But what happens is that most of the time the Main thread will wait forever at one of the WaitOne() seemingly at random.
Also I had to comment-out some parts of my code out because it led to even more unexpected behaviour (I.e somehow after each thread finished the main thread would jump back into the for clause and cause a IndexOutOfBounds)
class Threading
{
static Mutex CM;
static List<Manga> SharedList;
static ManualResetEvent CEvent = new ManualResetEvent(false);
static ManualResetEvent Event1 = new ManualResetEvent(false);
static ManualResetEvent Event2 = new ManualResetEvent(false);
static ManualResetEvent Event3 = new ManualResetEvent(false);
static ManualResetEvent Event4 = new ManualResetEvent(false);
public List<Manga> ThreadedMangaIndexCrawl(int MaxThreads)
{
CM = new Mutex(false);
SharedList = new List<Manga>();
ManualResetEvent[] evs = new ManualResetEvent[4];
evs[0] = Event1; // Event for t1
evs[1] = Event2; // Event for t2
evs[2] = Event3; // Event for t3
evs[3] = Event4; // Event for t4
/*for (int i = 0; i < MaxThreads + 1; i++)
{
if (i > MaxThreads)
{ break; }
Thread t = new Thread(() => this.StartIndexCrawling(1,i,i+1,evs[i]));
t.Start();
}*/
int i = 0;
Thread t1 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i]));
t1.Name = "Thread" + i;
t1.Start();
i++;
Thread t2 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i]));
t2.Name = "Thread" + i;
t2.Start();
i++;
Thread t3 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i]));
t3.Name = "Thread" + i;
t3.Start();
i++;
Thread t4 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i]));
t4.Name = "Thread" + i;
t4.Start();
/* foreach (var e in evs)
{
e.WaitOne();
}*/
evs[0].WaitOne();
evs[1].WaitOne();
evs[2].WaitOne();
evs[3].WaitOne();
return SharedList;
}
void StartIndexCrawling(int Target, int Start, int End, ManualResetEvent E)
{
Thread.Sleep(1000);
CM.WaitOne();
CM.ReleaseMutex();
E.Set();
}
}
Any help would be great
Most likely, all four threads will execute:
this.StartIndexCrawling(1, 3, 3 + 1, evs[4]);
This has to do with your use of closures. All four threads will be bound to the variable i and use whatever value it has once the code is executed (and not the value when the Thread object is created).
Your code is unlikely to work if all four threads use the same value.
See Codo's answer.
Here is what you should do to solve it:
int i = 0;
Thread t1 = new Thread(() => this.StartIndexCrawling(1, 0, 1, Event1));
t1.Name = "Thread" + i;
t1.Start();
i++;
Thread t2 = new Thread(() => this.StartIndexCrawling(1, 1, 2, Event2));
t2.Name = "Thread" + i;
t2.Start();
i++;
Thread t3 = new Thread(() => this.StartIndexCrawling(1, 2, 3, Event3));
t3.Name = "Thread" + i;
t3.Start();
i++;
Thread t4 = new Thread(() => this.StartIndexCrawling(1, 3, 4, Event4));
t4.Name = "Thread" + i;
t4.Start();

When All Threads Are Complete

This is my first real attempt at using multithreading, I want to know how I can tell when all of my tasks groups are done running:
for (int i = 0; i < taskGroups.Count(); i++) {
ThreadStart t = delegate { RunThread(taskGroups[i]); };
new Thread(t).Start();
}
if(allThreadsComplete){ //???
}
Any help would be much appreciated
Addendum:
ThreadStart[] threads = new ThreadStart[taskGroups.Count()];
for (int i = 0; i < taskGroups.Count(); i++) {
threads[i] = new ThreadStart[]
threads[i] = delegate { RunThread(taskGroups[i]); };
new Thread(t).Start();
}
bool threadsComplete = false;
while(!threadsComplete){
for(int i=0;i<taskGroups.Count();i++){
if(threads[i].State == complete)
threadsComplete = true;
}
}
You need to store all your threads, and then call Thread.Join().
Something like this:
List<Thread> threads = new List<Thread>();
for (int i = 0; i < taskGroups.Count(); i++) {
int temp = i; //This fixes the issue with i being shared
Thread thread = new Thread(() => RunThread(taskGroups[temp]));
threads.Add(thread);
thread.Start();
}
foreach (var thread in threads) {
thread.Join();
}
If you're using 3.5 then you can write your own CountdownEvent, if you're using 4.0 then you can use the built in CountdownEvent to do something like this:
CountdownEvent = new CountdownEvent(taskGroups.Count());
for (int i = 0; i < taskGroups.Count(); i++)
{
int item = i; // copy i locally
ThreadStart t = delegate
{
RunThread(taskGroups[item]);
latch.Signal();
};
new Thread(t).Start();
}
latch.Wait();
The latch.Wait() will cause your code to block until the threads have all finished. Furthermore, you might want to change the way you start your thread a bit:
CountdownEvent = new CountdownEvent(taskGroups.Count());
for (int i = 0; i < taskGroups.Count(); i++)
{
int item = i; // copy i locally
Thread t = new Thread(()=>
{
RunThread(taskGroups[item]);
latch.Signal();
});
t.IsBackground = true;
t.Start();
}
latch.Wait();
Note that I'm setting the thread to background: this your application from hanging when exit and not all threads have finished (i.e. prevents ghost or daemon threads).
You can use Thread.Join to make sure that each individual thread has finished running.
You can add public static integer field to the main thread, in each child thread increase it by one when it's completed then in the main thread wait (in a loop) until that variable is equal to the taskGroups.Count().
First of all consider switching to the new asynchronous pattern using Task.
Anyway if you want to wait for all your threads you can call Thread.Join:
var threads = new List<Thread>();
for (int i = 0; i < taskGroups.Count(); i++) {
ThreadStart t = delegate { RunThread(taskGroups[i]); };
var thread = new Thread(t);
threads.Add(thread);
thread.Start();
}
threads.ForEach(a => a.Join());
Remember that you can also pass a timeout parameter that will wait until the thread finishes only if it doesn't takes more than the time you passed in.
You can check the ThreadState property of each Thread object.

C# using loop to start threads and pass parameters

In below sample code, I use lambda function to make 3 threads doing different things. My goal is make the thread count configurable, so I was thinking using a loop to start threads. But I always got in static function can't call non-static members error. Can the community help me or direct me to a tutorial? Thanks a lot!
My Code:
internal class FeedClient
{
private static void Main(string[] args)
{
int iteration = 10;
int ranSleepTime = 1000;
var obj = new MyClass();
var threads = new Thread[3];
(threads[0] = new Thread(() =>
{
Random random = new System.Random();
for (int i = 0; i < iteration; i++)
{
obj.MyMethod("my string 1");
Thread.Sleep(random.Next(ranSleepTime));
}
})).Start();
(threads[1] = new Thread(() =>
{
Random random = new System.Random();
for (int i = 0; i < iteration; i++)
{
obj.MyMethod("my string 2");
Thread.Sleep(random.Next(ranSleepTime));
}
})).Start();
(threads[2] = new Thread(() =>
{
Random random = new System.Random();
for (int i = 0; i < iteration; i++)
{
obj.MyMethod("my string 3");
Thread.Sleep(random.Next(ranSleepTime));
}
})).Start();
foreach (Thread thread in threads)
{
thread.Join();
}
obj.Close(false);
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
Desired look:
for(int i=0;i<3;i++){
threads[i] = new Thread(func); // func is the lambda function
threads[i].Start(myData[i]); // myData[] may be a string array
}
The error message seems to indicate that you are attempting to use an instance member from a static method somewhere. Naturally that is not allowed since a static method does not have a this reference. Here is how I would refactor your code.
public static void Main()
{
string[] myData = GetStringArray();
int iteration = 10;
int ranSleepTime = 1000;
var obj = new MyClass();
var threads = new Thread[myData.Length];
for (int i = 0; i < threads.Length; i++)
{
int captured = i; // This is required to avoid capturing the loop variable.
threads[i] = new Thread(
() =>
{
var random = new Random();
for (int i = 0; i < iteration; i++)
{
obj.MyMethod(myData[captured]);
Thread.Sleep(random.Next(ranSleepTime));
}
});
threads[i].Start();
}
foreach (Thread thread in threads)
{
thread.Join();
}
obj.Close(false);
}
I must mention, however, that creating new threads in an unbounded loop is generally undesirable. If the loop has a tight bound then maybe, but I would have to get a better understanding of the problem before making any further comments regarding this point.

Categories

Resources