C# Multithread dequeue List<string> - c#

First of all, sorry for my english. I'm doing some C# exercices but I'm in a trouble with this.
Actually, I need to create 2 threads using Thread class. These threads needs to Dequeue items from a List (I have created a Dequeue method to do that) but I need to configure these 2 threads to Deqeueue this List at the same time. Aditionaly, this method needs to show the thread that executed him and the removed the object.
That's the method called by Thread:
private static object Lock = new object();
public string Consume()
{
string result = "";
while (StringList.Count > 0)
{
lock (Lock)
{
result = Dequeue();
}
}
return result;
}
And the thread call:
Thread t1 = new Thread(() => { Console.WriteLine("Thread 1: " + QC.Consume()); });
Thread t2 = new Thread(() => { Console.WriteLine("Thread 2: " + QC.Consume()); });
t1.Start();
t2.Start();
Actually, the program "is working" but it is only being executed by an unique thread. I don't know how to dequeue items from list at the same time with different threads + show which thread dequeued the item.
I'm not asking just to know if someone know the problem, I want to understand the problem and solve it.
Thanks to all!

Related

how to transfer some info to other?

I have two threads. How to get data from thread1 to thread2. It means, whe thread1 has done its work, it has some data, and this data must be used in the second "thread2". How to realize it ?
Here is code, but what to do..now ?
static void Main(string[] args)
{
Thread t1 = new Thread(thread1);
t1.Start();
Thread t2 = new Thread(thread2);
t2.Start();
}
static void thread1()
{
string newstring="123";
}
static void thread2()
{
//what to do here...what code will be here?
Console.WriteLine(newstring);
}
In thread1 can be whatever, but i need to get this "whatever", than i can use it in thread2
Data, which is used by both Thread must be commonly shared between both thread.
usually it is called common resource.
One this you must note that you have to achieve synchronization here.
As both threads are running independently and also reading/writing common data, chances of Race Condition is pretty high. To prevent such cases, you must implement synchronization on reading/writing data (on common object).
refere below code, where CommonResource is common between both threads and synchronization has been achieved by locking
In your example, one thread is writing data and other thread is reading data. If we don't implement Synchronization, there are chances that while thread 1 is writing new data, but thread 2 (because it is not waiting for thread 1 to complete it's task first) will bring old data (or invalid data).
Situation goes worst when there are multiple threads which are writing data, without waiting for other threads to complete their writing.
public class CommonResourceClass
{
object lockObj;
//Note: here main resource is private
//(thus not in scope of any thread)
string commonString;
//while prop is public where we have lock
public string CommonResource
{
get
{
lock (lockObj)
{
Console.WriteLine(DateTime.Now.ToString() + " $$$$$$$$$$$$$$$ Reading");
Thread.Sleep(1000 * 2);
return commonString;
}
}
set
{
lock (lockObj)
{
Console.WriteLine(DateTime.Now.ToString() + " ************* Writing");
Thread.Sleep(1000 * 5);
commonString = value;
}
}
}
public CommonResourceClass()
{
lockObj = new object();
}
}
and Thread calling be like
static CommonResourceClass commonResourceClass;
static void Main(string[] args)
{
commonResourceClass = new CommonResourceClass();
Thread t1 = new Thread(ThreadOneRunner);
Thread t2 = new Thread(ThreadTwoRunner);
t1.Start();
t2.Start();
}
static void ThreadOneRunner()
{
while(true)
{
Console.WriteLine(DateTime.Now.ToString() + " *******Trying To Write");
commonResourceClass.CommonResource = "Written";
Console.WriteLine(DateTime.Now.ToString() + " *******Writing Done");
}
}
static void ThreadTwoRunner()
{
while(true)
{
Console.WriteLine(DateTime.Now.ToString() + " $$$$$$$Trying To Read");
string Data = commonResourceClass.CommonResource;
Console.WriteLine(DateTime.Now.ToString() + " $$$$$$$Reading Done");
}
}
Output of it:
Note That, reading is taking 2 seconds and writing is taking 5 seconds, so reading is supposed to be faster. But if writing is going on, reading must wait till writing done.
you can clearly see in output, as one thread is trying to read or write, it cannot do it while other thread is performing it's task.

ThreadStateException: Thread has not been started when trying to join a thread

just recently i faced with such a question on an interview
what would be the output of methid 'Calculate' execution:
public void Calculate()
{
var threads = Enumerable.Range(0, 50).Select(x =>
{
var thread = new Thread(DoWork)
{
Name = x.ToString()
};
return thread;
});
foreach (var thread in threads)
{
thread.Start();
}
foreach (var thread in threads)
{
thread.Join();
}
}
private void DoWork()
{
Console.WriteLine("Start()");
}
i checked it in VS and was surprised that ThreadStateException is thrown on line 'thread.Join();'. using debugger i found out that thread is not started.
it seems that when we go through the 2nd foreach we deal with another collection of threads. Can anyone please explain in details WHY exception is thrown?
Thanks in advance!
threads is an IEnumerable, not a list, and enumerating threads calls the
var thread = new Thread(DoWork)
{
Name = x.ToString()
};
return thread;
lambda 50 times, thus creating entirely new Threads.
If you wanted to distill the IEnumerable down to a concrete list of 50 threads, you'd need to call
var listOfThreads = threads.ToList();
and then use listOfThreads

Get status of thread

I am running a thread in which mail is being sent. How can I know that a thread has completed its execution?
new Thread(x => SendMail(node.Attributes["id"].Value.ToString(), node["fname"].InnerText + " " + node["lname"].InnerText, 500, node["email"].InnerText)).Start();
var thr = new Thread(x => SendMail(node.Attributes["id"].Value.ToString(), node["fname"].InnerText + " " + node["lname"].InnerText, 500, node["email"].InnerText));
thr.Start();
thr.Join();//In this place main thread will wait
You should keep a reference to the thread instance you create and then check the ThreadState. You can also check the IsAlive property to see if the thread is currently executing or not.
It depends on what your environment is. You can, for example, avoid at all Threads by using Tasks and subscribing to the continuation.
e.g.
var task = Task.Run(DoSomething)
.ContinueWith(a => Whatever())
Or by using the convenience keywords given by C# 5:
var task = await Task.Run(DoSomething);
Whatever();
If you MUST use threads I recommend to pass a delegate and when the e-mail has finished you have just to call it:
// Outside the thread
private Action callback;
// Before starting the thread
callback = MyMethod/*Or a lambda if you want*/;
// In the thread action
Action<object> threadBody = x =>
{
SendMail(node.Attributes["id"].Value.ToString(), node["fname"].InnerText + " " + node["lname"].InnerText, 500, node["email"].InnerText);
callback();
};
Another variation is to use the ThreadPool.QueueUserWorkItem in combination with ManualResetEvent:
Such as:
private void DoWork()
{
List<ManualResetEvent> events = new List<ManualResetEvent>();
//in case you need to loop through multiple email addresses
//use the foreach here, assuming that the items is a list.
//foreach(var item in items)
//{
var resetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(arg =>
{
SendMail(node.Attributes["id"].Value.ToString(),
node["fname"].InnerText + " " + node["lname"].InnerText,
500, node["email"].InnerText);
resetEvent.Set();
});
events.Add(resetEvent);
//} <- closes the foreach loop
//WaitHandle.WaitAll waits for all the threads to finish.
WaitHandle.WaitAll(events.ToArray());
MessageBox.Show("Mails are sent", "Notification");
}
This would be especially usefull in case you want to loop through a list or array of email-addresses and start a thread for each mail individually.
In your case if you want to do other things while waiting for the mails being sent. You could simply run the code above in a backgroundthread and when the message shows up you know work is completed.
public void StartMailThread()
{
Thread myThread = new Thread(DoWork)
{
IsBackground = true,
Name = "MailThread"
};
myThread.Start();
}
Although, to start a threadpool using a thread seems a bit weird to me.
Beside Andrew's Answer you can use BackgroundWorker It has already has RunWorkerCompleted event
BackgroundWorker

C# Threading in Window service creating issue

I have issue with email sending window service. The service starts after every three minutes delay and get messages that are to send from the db, and start sending it. Here is how the code looks like:
MessageFilesHandler MFHObj = new MessageFilesHandler();
List<Broadcostmsg> imidiateMsgs = Manager.GetImidiateBroadCastMsgs(conString);
if (imidiateMsgs.Count > 0)
{
// WriteToFileImi(strLog);
Thread imMsgThread = new Thread(new ParameterizedThreadStart(MFHObj.SendImidiatBroadcast));
imMsgThread.IsBackground = true;
imMsgThread.Start(imidiateMsgs);
}
This sends messages to large lists, and take long to complete sending to a larger list. now the problem occurs when on message is still sending and the service get a new message to send, the previous sending is haulted and new message sending started, although i am using threads, each time service get message to send it initiate a new thread.
Can u please help where i am doing mistake in the code.
I think you are using your code inside a loop which WAITS for new messages, did you manage those waits?? let's see:
while(imidiateMsgs.Count == 0)
{
//Wait for new Message
}
//Now you have a new message Here
//Make a new thread to process message
there are different methods for that wait, I suggest using BlockingQueues:
In public area:
BlockingCollection<Broadcostmsg> imidiateMsgs = new BlockingCollection<Broadcostmsg>();
In your consumer(thread which generates messages):
SendImidiatBroadcast = imidiateMsgs.Take();//this will wait for new message
//Now you have a new message Here
//Make a new thread to process message
In producer(thread which answers messages):
imidiateMsgs.Add(SendImidiatBroadcast);
And you have to use thread pool for making new threads each time to answer messages, don' initialize new thread each time.
It looks like requirement is to build a consumer producer queue. In which producer will keep adding message to a list and consumer would pick item from that list and do some work with it
Only worry for me is, you are each time creating a new Thread to send email rather than picking threads from thread pool. If you keep on creating more and more thread, performance of your application will degrade due to over head created by context switching.
If you are using .Net framwe work 4.0, the soultion become pretty easy. You could use System.Collections.Concurrent.ConcurrentQueue for en-queuing and dequeuing your items. Its thread safe, so no lock objects required. Use Tasks to process your messages.
BlockingCollection takes an IProducerConsumerCollection in its constructor, or it will use a ConcurrentQueue by default if you call its empty constructor.
So to enqueue your messages.
//define a blocking collectiom
var blockingCollection = new BlockingCollection<string>();
//Producer
Task.Factory.StartNew(() =>
{
while (true)
{
blockingCollection.Add("value" + count);
count++;
}
});
//consumer
//GetConsumingEnumerable would wait until it find some item for work
// its similar to while(true) loop that we put inside consumer queue
Task.Factory.StartNew(() =>
{
foreach (string value in blockingCollection.GetConsumingEnumerable())
{
Console.WriteLine("Worker 1: " + value);
}
});
UPDATE
Since you are using FrameWork 3.5. I suggest you have a look at Joseph Albahari's implementation of Consumer/Producer Queue. Its one of the best that you would ever find out.
Taking the code directly from above link
public class PCQueue
{
readonly object _locker = new object();
Thread[] _workers;
Queue<Action> _itemQ = new Queue<Action>();
public PCQueue (int workerCount)
{
_workers = new Thread [workerCount];
// Create and start a separate thread for each worker
for (int i = 0; i < workerCount; i++)
(_workers [i] = new Thread (Consume)).Start();
}
public void Shutdown (bool waitForWorkers)
{
// Enqueue one null item per worker to make each exit.
foreach (Thread worker in _workers)
EnqueueItem (null);
// Wait for workers to finish
if (waitForWorkers)
foreach (Thread worker in _workers)
worker.Join();
}
public void EnqueueItem (Action item)
{
lock (_locker)
{
_itemQ.Enqueue (item); // We must pulse because we're
Monitor.Pulse (_locker); // changing a blocking condition.
}
}
void Consume()
{
while (true) // Keep consuming until
{ // told otherwise.
Action item;
lock (_locker)
{
while (_itemQ.Count == 0) Monitor.Wait (_locker);
item = _itemQ.Dequeue();
}
if (item == null) return; // This signals our exit.
item(); // Execute item.
}
}
}
The advantage with this approach is you can control the number of Threads that you need to create for optimized performance. With threadpools approach, although its safe, you can not control the number of threads that could be created simultaneously.

Multithreading: When would I use a Join?

I see online that it says I use myThread.Join(); when I want to block my thread until another thread finishes. (One of the things I don't get about this is what if I have multiple threads).
But generally, I just don't get when I'd use .Join() or a condition that it's useful for. Can anyone please explain this to me like I'm a fourth grader? Very simple explanation to understand will get my answer vote.
Let's say you want to start some worker threads to perform some kind of calculation, and then do something afterwards with all the results.
List<Thread> workerThreads = new List<Thread>();
List<int> results = new List<int>();
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(() => {
Thread.Sleep(new Random().Next(1000, 5000));
lock (results) {
results.Add(new Random().Next(1, 10));
}
});
workerThreads.Add(thread);
thread.Start();
}
// Wait for all the threads to finish so that the results list is populated.
// If a thread is already finished when Join is called, Join will return immediately.
foreach (Thread thread in workerThreads) {
thread.Join();
}
Debug.WriteLine("Sum of results: " + results.Sum());
Oh yeah, and don't use Random like that, I was just trying to write a minimal, easily understandable example. It ends up not really being random if you create new Random instances too close in time, since the seed is based on the clock.
In the following code snippet, the main thread calls Join() which causes it to wait for all spawned threads to finish:
static void Main()
{
Thread regularThread = new Thread(ThreadMethod);
regularThread.Start();
Thread regularThread2 = new Thread(ThreadMethod2);
regularThread2.Start();
// Wait for spawned threads to end.
regularThread.Join();
Console.WriteLine("regularThread returned.");
regularThread2.Join();
Console.WriteLine("regularThread2 returned.");
}
Note that if you also spun up a thread from the thread pool (using QueueUserWorkItem for instance), Join would not wait for that background thread. You would need to implement some other mechanism such as using an AutoResetEvent.
For an excellent introduction to threading, I recommend reading Joe Albahari's free Threading in C#
This is very simple program to demonstrate usage of Thread Join.Please follow my comments for better understanding.Write this program as it is.
using System;
using System.Threading;
namespace ThreadSample
{
class Program
{
static Thread thread1, thread2;
static int sum=0;
static void Main(string[] args)
{
start();
Console.ReadKey();
}
private static void Sample() { sum = sum + 1; }
private static void Sample2() { sum = sum + 10; }
private static void start()
{
thread1 = new Thread(new ThreadStart(Sample));
thread2 = new Thread(new ThreadStart(Sample2));
thread1.Start();
thread2.Start();
// thread1.Join();
// thread2.Join();
Console.WriteLine(sum);
Console.WriteLine();
}
}
}
1.First time run as it is (with comments) : Then result will be 0(initial value) or 1(when thread 1 finished) or 10 (Or thread finished)
2.Run with removing comment thread1.Join() : Result should be always more than 1.because thread1.Join() fired and thread 1 should be finished before get the sum.
3.Run with removing all coments :Result should be always 11
Join is used mainly when you need to wait that a thread (or a bunch of them) will terminate before proceding with your code.
For this reason is also particular useful when you need to collect result from a thread execution.
As per the Arafangion comment below, it's also important to join threads if you need to do some cleaning/housekeeping code after having created a thread.
Join will make sure that the treads above line is executed before executing lines below.
Another example, when your worker thread let's say reads from an input stream while the read method can run forever and you want to somehow avoid this - by applying timeout using another watchdog thread:
// worker thread
var worker = new Thread(() => {
Trace.WriteLine("Reading from stream");
// here is the critical area of thread, where the real stuff happens
// Sleep is just an example, simulating any real operation
Thread.Sleep(10000);
Trace.WriteLine("Reading finished");
}) { Name = "Worker" };
Trace.WriteLine("Starting worker thread...");
worker.Start();
// watchdog thread
ThreadPool.QueueUserWorkItem((o) => {
var timeOut = 5000;
if (!worker.Join(timeOut))
{
Trace.WriteLine("Killing worker thread after " + timeOut + " milliseconds!");
worker.Abort();
}
});
Adding a delay of 300ms in method "Sample" and a delay of 400ms in "Sample2" from devopsEMK's post would make it easier to understand.
By doing so you can observe that by removing the comment from "thread1.Join();" line, the main thread waits for the "thread1" to complete and only after moves on.

Categories

Resources