I'm new to multi-threading, I want to achieve something like below using C#.
Thread 0 printed 0
Thread 1 printed 1
Thread 2 printed 2
Thread 3 printed 3
Thread 4 printed 4
Thread 5 printed 5
Thread 6 printed 6
Thread 7 printed 7
Thread 8 printed 8
Thread 9 printed 9
Thread 0 printed 10
Thread 1 printed 11
Thread 2 printed 12
Thread 3 printed 13
Thread 4 printed 14
Thread 5 printed 15
Thread 6 printed 16
Thread 7 printed 17
Thread 8 printed 18
Thread 9 printed 19
.
.
.
Thread 10 printed 99.
I have done something like this but of course, requirement is beyond.
class Program
{
static int count = 0; // the shared counter from 1 to 100
static void Main(string[] args)
{
Thread[] tr = new Thread[10]; // i have created 10 threads each one will print 10 cyclic values
string result = "";
int cc = 0;
while (cc!=10) {
for (int i = 0; i < 10; i++)
{
tr[i] = new Thread(new ThreadStart(printTill10));
tr[i].Start();
tr[i].Join();
}
cc++;
}
}
string s = "";
static void printTill10()
{
Console.WriteLine(++count+ "Printed by thread #"+
Thread.CurrentThread.ManagedThreadId);
}
}
I am confused either I should use a lock or something like monitor.wait or monitor.pulse etc.
Thanks for any help.
Do it like so:
First declare a variable count in the class so that it can be accessed by all threads. Also, create an object locker that will allow us to lock the count variable.
static int count;
static object locker;
Then, create the method that contains the code that the threads will all run:
static void printTill10()
{
while (true)
{
lock (locker)
{
if (count < 100)
{
count++;
Console.WriteLine(string.Format("Thread {0} printed {1}", Thread.CurrentThread.ManagedThreadId.ToString(), count.ToString()));
}
}
}
}
What this code does when run is the following:
Enters a while loop which loops forever.
Locks locker to make sure only one operation is being performed on count at a time.
Checks to see if count is under 100.
Increases count by one.
Prints a string exactly like the one you're trying to get (I used String.Format instead of concentration because its neater)
Simple right? This is the code that our threads will run. Now we can focus on the multithreading part.
static void Main()
{
count = 0; // Be sure to give count an initial value to prevent an exception from being thrown.
locker = new object();
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++)
{
threads[i] = new Thread(() => printTill100());
threads[i].Start();
}
Thread.Sleep(Timeout.Infinite);
}
Our Main does the following:
Gives an initial value to the count and locker variables.
Creates an array to put our threads in.
Enters a for loop which populates the array with threads and starts them.
Makes the main thread (the one code runs in by default) wait forever (specified by Timeout.Infinite. This last bit is an important one. By default, all code runs in a single thread called the main thread. If we don't tell it to wait, it will exit after the loop is done, closing the program. It will not wait until our other threads are finished.
There is just one thing you have missed while writing code in
printTill10()
method.
Just put one lock block in printTill10() method like this.
static void printTill10()
{
lock (_locker)
{
Console.WriteLine(++count + "Printed by thread #" + Thread.CurrentThread.ManagedThreadId);
}
}
and also declare locker object in the Pragram class like
static readonly object _locker = new object();
Here is the complete code
class Program
{
static int count = 0; // the shared counter from 1 to 100
static readonly object _locker = new object();
static void Main(string[] args)
{
Thread[] tr = new Thread[10]; // i have created 10 threads each one will print 10 cyclic values
string result = "";
int cc = 0;
while (cc != 10)
{
for (int i = 0; i < 10; i++)
{
tr[i] = new Thread(new ThreadStart(printTill10));
tr[i].Start();
tr[i].Join();
}
cc++;
}
}
string s = "";
static void printTill10()
{
lock (_locker)
{
Console.WriteLine(++count + "Printed by thread #" + Thread.CurrentThread.ManagedThreadId);
}
}
}
It will work as per your requirement. :)
After a continuous try, I got to complete the requirements of my task. Here is the code:
using System;
using System.Threading;
public class EntryPoint
{
static private int counter = 0;
static private object theLock = new Object();
static object obj = new object();
static private void count()
{
{
for (int i = 0; i < 10; i++)
{
lock (theLock)
{
Console.WriteLine("Count {0} Thread{1}",
counter++, Thread.CurrentThread.GetHashCode());
if (counter>=10)
Monitor.Pulse(theLock);
Monitor.Wait(theLock); } }}
}
static void Main()
{
Thread[] tr = new Thread[10];
for (int i = 0; i < 10; i++)
{
tr[i] = new Thread(new ThreadStart(count));
tr[i].Start();
}
}
}
Monitor maintains a ready queue in a sequential order hence I achieved what I wanted:
Related
I am new to C# and still learning the threading concept. I wrote a program which is as follows
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApplication17
{
class Program
{
static void Main(string[] args)
{
System.Threading.ThreadStart th1 = new System.Threading.ThreadStart(prnt);
Thread th = new Thread(th1);
th.Start();
bool t = th.IsAlive;
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i + "A");
}
}
private static void prnt()
{
for (int i = 0; i < 10; i ++)
{
Console.WriteLine(i + "B");
}
}
}
}
I am expecting an output like :-
1A
2A
1B
3A
2B...
as I believe that both main thread and newly created thread should be executing simultaneously.
But the output is ordered , first the prnt function is called and then the Main method for loop is executed.
maybe a cicle of 10 is not enough to see the two thread running at same time.
use a longer loop or put a Thread.Sleep (100) within cycle iteration.
Starting a thread is quite expensive. What it happens, probably, is that you Main loop get executed before thread loop start, due to the time required for a thread to start
I agree with previous answers you need to add Thread.Sleep(some seconds * 1000)
I recommend you read this article about thread
https://msdn.microsoft.com/ru-ru/library/system.threading.thread(v=vs.110).aspx
static void Main(string[] args)
{
Thread th = new Thread(prnt);
th.Start();
for (int i = 0; i < 10; i++)
{
//sleep one second
Thread.Sleep(1000);
Console.WriteLine(i + "A");
}
//join the basic thread and 'th' thread
th.Join();
}
private static void prnt()
{
for (int i = 0; i < 10; i++)
{
//sleep one second
Thread.Sleep(1000);
Console.WriteLine(i + "B");
}
}
Updated: A process is used to isolate applications and threads run in the context of that process.
This way, it makes easier for the OS to manage different apps, managing crashes and context switching (slots of time provided to each app to be executed by the CPU). The idea behind is simply run threads during a predefined slot of time, when the time permitted for an app to run is over, the CPU switches to other thread to be executed.
Use the Threading class for small asynchronous tasks in your applications.
See how in the following example you can create a new thread using the System.Threading namespace. Notice how t.Join() is called to wait for the new thread to finish.
Note that the Spleep(1) will force to change the context and that's is what makes the difference with you example. Try to change it back to zero and see the results.
using System;
using System.Threading;
namespace Chapter1
{
public static class Threads1
{
public static void ThreadMethod()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("ThreadProc: {0}", i);
Thread.Sleep(1);
}
}
public static void Main(string[] args)
{
Thread t = new Thread(new ThreadStart(ThreadMethod));
t.Start();
for (int i = 0; i < 4; i++)
{
Console.WriteLine("Main thread: Do some work.");
Thread.Sleep(1);
}
t.Join();
Console.Read();
}
}
}
// OUTPUT:
//Main thread: Do some work.
//ThreadProc: 0
//ThreadProc: 1
//Main thread: Do some work.
//ThreadProc: 2
//Main thread: Do some work.
//ThreadProc: 3
//Main thread: Do some work.
//ThreadProc: 4
//ThreadProc: 5
//ThreadProc: 6
//ThreadProc: 7
//ThreadProc: 8
//ThreadProc: 9
This class uses lock and Interlocked.
Both increaseCount.with_lock.Run(); and increaseCount.with_interlock.Run(); prints between 96-100.
I am expecting both of them to print always 100. What did I make mistake?
public static class increaseCount {
public static int counter = 0;
public static readonly object myLock = new object();
public static class with_lock {
public static void Run() {
List<Thread> pool = new List<Thread>();
for(int i = 0; i < 100; i++) {
pool.Add(new Thread(f));
}
Parallel.ForEach(pool, x => x.Start());
Console.WriteLine(counter); //should print 100
}
static void f() {
lock(myLock) {
counter++;
}
}
}
public static class with_interlock {
public static void Run() {
List<Thread> pool = new List<Thread>();
for(int i = 0; i < 100; i++) {
pool.Add(new Thread(f));
}
Parallel.ForEach(pool, x => x.Start());
Console.WriteLine(counter);//should print 100
}
static void f() {
Interlocked.Add(ref counter, 1);
}
}
}
In both cases, you start up your threads but you don't wait for them to complete so you don't reach the 100 before you print the result and the app closes.
If after you start all thread you would wait for all these threads to complete with Thread.Join you would always get the correct result:
List<Thread> pool = new List<Thread>();
for (int i = 0; i < 100; i++)
{
pool.Add(new Thread(f));
}
Parallel.ForEach(pool, x => x.Start());
foreach (var thread in pool)
{
thread.Join();
}
Console.WriteLine(counter);
Note: This seems like a test of some kind, but you should know that blocking multiple threads on a single lock is a huge waste of resources.
I believe it's because your Parallel.Foreach call simply calls start on all the threads in pool but they haven't necessarily completed by the time the loops finished and the Console.WriteLine is called. If you were to insert a Thread.Sleep(5000); // 5s sleep or similar before the Console.WriteLine it would likely always print out what you expect.
Your code is fine. The only problem is your expectation. Basically, not all 100 threads get to run untill the counter is displayed. Try putting a Thread.Sleep(1000) before the Console.WriteLine(counter) and you shall see what I mean.
Edit: wrongly posted as a comment the first time.
I am trying to dynamically create X amount of threads(specified by user) then basically have all of them execute some code at the exact same time in intervals of 1 second.
The issue I am having is that the task I am trying to complete relies on a loop to determine if the current IP is equal to the last. (It scans hosts) So since I have this loop inside, it is going off and then the other threads are not getting created, and not executing the code. I would like them to all go off at the same time, wait 1 second(using a timer or something else that doesnt lock the thread since the code it is executing has a timeout it waits for.) Can anyone help me out? Here is my current code:
int threads = Convert.ToInt32(txtThreads.Text);
List<Thread> workerThreads = new List<Thread>();
string from = txtStart.Text, to = txtEnd.Text;
uint current = from.ToUInt(), last = to.ToUInt();
ulong total = last - current;
for (int i = 0; i < threads; i++)
{
Thread thread = new Thread(() =>
{
for (int t = 0; t < Convert.ToInt32(total); t += i)
{
while (current <= last)
{
current = Convert.ToUInt32(current + t);
var ip = current.ToIPAddress();
doSomething(ip);
}
}
});
workerThreads.Add(thread);
thread.Start();
}
Don't use a lambda as the body of your thread, otherwise the i value isn't doing what you think it's doing. Instead pass the value into a method.
As for starting all of the threads at the same time do something like the following:
private object syncObj = new object();
void ThreadBody(object boxed)
{
Params params = (Params)boxed;
lock (syncObj)
{
Monitor.Wait(syncObj);
}
// do work here
}
struct Params
{
// passed values here
}
void InitializeThreads()
{
int threads = Convert.ToInt32(txtThreads.Text);
List<Thread> workerThreads = new List<Thread>();
string from = txtStart.Text, to = txtEnd.Text;
uint current = from.ToUInt(), last = to.ToUInt();
ulong total = last - current;
for (int i = 0; i < threads; i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(this.ThreadBody, new Params { /* initialize values here */ }));
workerThreads.Add(thread);
thread.Start();
}
lock(syncObj)
{
Monitor.PulseAll(syncObj);
}
}
You're running into closure problems. There's another question that somewhat addresses this, here.
Basically you need to capture the value of i as you create each task. What's happening is by the time the task gets around to actually running, the value of i across all your tasks is the same -- the value at the end of the loop.
This is further to my question here
By doing some reading .... I moved away from Semaphores to ThreadPool.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ThreadPoolTest
{
class Data
{
public int Pos { get; set; }
public int Num { get; set; }
}
class Program
{
static ManualResetEvent[] resetEvents = new ManualResetEvent[20];
static void Main(string[] args)
{
int s = 0;
for (int i = 0; i < 100000; i++)
{
resetEvents[s] = new ManualResetEvent(false);
Data d = new Data();
d.Pos = s;
d.Num = i;
ThreadPool.QueueUserWorkItem(new WaitCallback(Process), (object)d);
if (s >= 19)
{
WaitHandle.WaitAll(resetEvents);
Console.WriteLine("Press Enter to Move forward");
Console.ReadLine();
s = 0;
}
else
{
s = s + 1;
}
}
}
private static void Process(object o)
{
Data d = (Data) o;
Console.WriteLine(d.Num.ToString());
Thread.Sleep(10000);
resetEvents[d.Pos].Set();
}
}
}
This code works and I am able to process in the sets of 20. But I don't like this code because of WaitAll. So let's say I start a batch of 20, and 3 threads take longer time while 17 have finished. Even then I will keep the 17 threads as waiting because of the WaitAll.
WaitAny would have been good... but it seems rather messy that I will have to build so much of control structures like Stacks, Lists, Queues etc in order to use the pool efficiently.
The other thing I don't like is that whole global variable in the class for resetEvents. because this array has to be shared between the Process method and the main loop.
The above code works... but I need your help in improving it.
Again... I am on .NET 2.0 VS 2008. I cannot use .NET 4.0 parallel/async framework.
There are several ways you can do this. Probably the easiest, based on what you've posted above, would be:
const int MaxThreads = 4;
const int ItemsToProcess = 10000;
private Semaphore _sem = new Semaphore(MaxThreads, MaxThreads);
void DoTheWork()
{
int s = 0;
for (int i = 0; i < ItemsToProcess; ++i)
{
_sem.WaitOne();
Data d = new Data();
d.Pos = s;
d.Num = i;
ThreadPool.QueueUserWorkItem(Process, d);
++s;
if (s >= 19)
s = 0;
}
// All items have been assigned threads.
// Now, acquire the semaphore "MaxThreads" times.
// When counter reaches that number, we know all threads are done.
int semCount = 0;
while (semCount < MaxThreads)
{
_sem.WaitOne();
++semCount;
}
// All items are processed
// Clear the semaphore for next time.
_sem.Release(semCount);
}
void Process(object o)
{
// do the processing ...
// release the semaphore
_sem.Release();
}
I only used four threads in my example because that's how many cores I have. It makes little sense to be using 20 threads when only four of them can be processing at any one time. But you're free to increase the MaxThreads number if you like.
So I'm pretty sure this is all .NET 2.0.
We'll start out defining Action, because I'm so used to using it. If using this solution in 3.5+, remove that definition.
Next, we create a queue of actions based on the input.
After that we define a callback; this callback is the meat of the method.
It first grabs the next item in the queue (using a lock since the queue isn't thread safe). If it ended up having an item to grab it executes that item. Next it adds a new item to the thread pool which is "itself". This is a recursive anonymous method (you don't come across uses of that all that often). This means that when the callback is called for the first time it will execute one item, then schedule a task which will execute another item, and that item will schedule a task that executes another item, and so on. Eventually the queue will run out, and they'll stop queuing more items.
We also want the method to block until we're all done, so for that we keep track of how many of these callbacks have finished through incrementing a counter. When that counter reaches the task limit we signal the event.
Finally we start N of these callbacks in the thread pool.
public delegate void Action();
public static void Execute(IEnumerable<Action> actions, int maxConcurrentItems)
{
object key = new object();
Queue<Action> queue = new Queue<Action>(actions);
int count = 0;
AutoResetEvent whenDone = new AutoResetEvent(false);
WaitCallback callback = null;
callback = delegate
{
Action action = null;
lock (key)
{
if (queue.Count > 0)
action = queue.Dequeue();
}
if (action != null)
{
action();
ThreadPool.QueueUserWorkItem(callback);
}
else
{
if (Interlocked.Increment(ref count) == maxConcurrentItems)
whenDone.Set();
}
};
for (int i = 0; i < maxConcurrentItems; i++)
{
ThreadPool.QueueUserWorkItem(callback);
}
whenDone.WaitOne();
}
Here's another option that doesn't use the thread pool, and just uses a fixed number of threads:
public static void Execute(IEnumerable<Action> actions, int maxConcurrentItems)
{
Thread[] threads = new Thread[maxConcurrentItems];
object key = new object();
Queue<Action> queue = new Queue<Action>(actions);
for (int i = 0; i < maxConcurrentItems; i++)
{
threads[i] = new Thread(new ThreadStart(delegate
{
Action action = null;
do
{
lock (key)
{
if (queue.Count > 0)
action = queue.Dequeue();
else
action = null;
}
if (action != null)
{
action();
}
} while (action != null);
}));
threads[i].Start();
}
for (int i = 0; i < maxConcurrentItems; i++)
{
threads[i].Join();
}
}
I am trying to understand threading concepts in .Net.
I am unable to use Yield() method. I want the control to go to a parallel thread when i becomes divisible by 10.
Please help.
Below is my sample code:
class ThreadTest
{
//Index i is declared as static so that both the threads have only one copy
static int i;
static void Main(string[] args)
{
Thread t = new Thread(WriteY);
i = 0;
//Start thread Y
t.Start();
//Do something on the main thread.
for (; i < 100; i++)
{
if (i % 10 == 0)
{
//Simulate Yield() function
Thread.Sleep(0);
Console.WriteLine("The X thread");
}
Console.Write(i + ":X ");
}
Console.ReadKey(true);
}
static void WriteY()
{
for (; i < 100; i++)
{
if (i % 10 == 0)
{
//Simulate Yield() function
Thread.Sleep(0);
Console.WriteLine("The Y thread");
}
Console.Write(i + ":Y ");
}
}
}
I get the compile time error:
System.Threading.Thread does not contain a definition for 'Yield'
Answered by Tudor. This method will only work on .Net 4.0 and upwards.
Ideally I would want one thread to start and want each thread to execute for 10 incremented of i each. With my current method, I either get all 'X' or all 'Y'.
Edit:
With inputs from Tudor and TheHe - I have been able to get alternate X and Y. The crux of the problem was usage of lock object. But the output of this code is not predictable.
Thread.Yield will simply enable the scheduler to select a different thread that is ready to run:
Causes the calling thread to yield execution to another thread that is
ready to run on the current processor. The operating system selects
the thread to yield to.
If other threads in your application are also waiting on that lock, you can yield all you want, they won't get a chance to run.
Btw, Yield is a .NET 4.0+ method. Make sure you're not targeting an earlier version.
Edit: IMO, to do what you want you should use events:
class Test
{
//Index i is declared as static so that both the threads have only one copy
static int i;
static AutoResetEvent parentEvent = new AutoResetEvent(true);
static AutoResetEvent childEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
Thread t = new Thread(WriteY);
i = 0;
//Start thread Y
t.Start();
// Print X on the main thread
parentEvent.WaitOne();
while (i < 100)
{
if (i % 10 == 0)
{
childEvent.Set();
parentEvent.WaitOne();
}
Console.Write(i + ":Y ");
i++;
}
t.Join();
}
static void WriteY()
{
childEvent.WaitOne();
while (i < 100)
{
if (i % 10 == 0)
{
parentEvent.Set();
childEvent.WaitOne();
}
Console.Write(i + ":X ");
i++;
}
}
}
Forget Thread.Yield; that is unrelated to what you are trying to do. Ultimately, you have a lock, which uses Monitor to synchronize access. Inside the lock, your thread exclusively has access. What you need to do is relinquish the lock temporarily; the way you do that is with Monitor.Wait. However, if you Wait, you also end up in the "waiting" queue rather than the "ready" queue, so in order to make sure that each thread gets attention, we also need to Pulse, both before the Wait, and also at the end (to make sure both threads get chance to exit). Here we go:
using System.Threading;
using System;
class ThreadTest
{
//Index i is declared as static so that both the threads have only one copy
static int i;
//The lock object
static readonly object locker = new object();
static void Main(string[] args)
{
Thread t = new Thread(WriteY);
i = 0;
//Start thread Y
t.Start();
lock (locker)
{
// Print X on the main thread
for (; i < 100; i++)
{
if (i % 10 == 0)
{
Monitor.PulseAll(locker); // move any "waiting" threads to the "ready" queue
Monitor.Wait(locker); // relinquish the lock, and wait for a pulse
Console.WriteLine("The X thread");
}
Console.Write(i + ":X ");
}
Monitor.PulseAll(locker);
}
Console.ReadKey(true);
}
static void WriteY()
{
lock (locker)
{
for (; i < 100; i++)
{
if (i % 10 == 0)
{
Monitor.PulseAll(locker); // move any "waiting" threads to the "ready" queue
Monitor.Wait(locker); // relinquish the lock, and wait for a pulse
Console.WriteLine("The Y thread");
}
Console.Write(i + ":Y ");
}
Monitor.PulseAll(locker); // move any "waiting" threads to the "ready" queue
}
}
}
from my point of view, you're locking "locker" in current thread and want to yield the current task to an other thread...
the lock is held by the first thread all the time -- it can't work?!
you have to manually lock the objects if you want to use multiple threads...