how to transfer some info to other? - c#

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.

Related

Parallel.Invoke and thread invocation - Clarification?

I have this code which creates a deadlock :
void Main()
{
ClassTest test = new ClassTest();
lock(test)
{
Task t1 = new Task(() => test.DoWorkUsingThisLock(1));
t1.Start();
t1.Wait();
}
}
public class ClassTest
{
public void DoWorkUsingThisLock(int i)
{
Console.WriteLine("Before " + i);
Console.WriteLine ("Current Thread ID is = "+Thread.CurrentThread.ManagedThreadId);
lock(this)
{
Console.WriteLine("Work " + i);
Thread.Sleep(1000);
}
Console.WriteLine("Done " + i);
}
}
Result :
Before 1
(and deadlock....)
I know that this is a bad practice to lock over instances beyond code's control or , this. But it's just for this question.
I can understand why a deadlock is created here.
The main thread acquires the lock(test) in main and then a new thread starts to invoke DoWorkUsingThisLock - there it tries to acquire a lock over the same instance variable and it's stuck ( because of t1.Wait() at main)
OK
But I've seen this answer here which also creates deadlock.
void Main()
{
ClassTest test = new ClassTest();
lock(test)
{
Parallel.Invoke (
() => test.DoWorkUsingThisLock(1),
() => test.DoWorkUsingThisLock(2)
);
}
}
public class ClassTest
{
public void DoWorkUsingThisLock(int i)
{
Console.WriteLine("Before ClassTest.DoWorkUsingThisLock " + i);
lock(this)
{
Console.WriteLine("ClassTest.DoWorkUsingThisLock " + i);
Thread.Sleep(1000);
}
Console.WriteLine("ClassTest.DoWorkUsingThisLock Done " + i);
}
}
The result is :
Before ClassTest.DoWorkUsingThisLock 1
Before ClassTest.DoWorkUsingThisLock 2
ClassTest.DoWorkUsingThisLock 1 // <---- how ?
ClassTest.DoWorkUsingThisLock Done 1
Question:
How come it DID acquire the lock for the first invocation (DoWorkUsingThisLock(1))? The lock at main is still blocked due to Parallel.Invoke which DOES block !
I don't understand how the thread has succeeded to enter the lock(this) section.
The Parallel class uses the current thread to do a part of the work. This is a nice performance optimization but it is observable in the case of thread-specific state.
The TPL has this kind of "inline execution" in many places and it causes a lot of trouble in different ways. Many programs are not made to deal with reentrancy.

Thread Pool with BlockingCollection

Problem: There are multiple threads accessing a resource. I need to limit their number to a constant MaxThreads. Threads who cannot enter the thread pool should get an error message.
Solution: I started using a BlockingCollection<string> pool in the algorithm below, but I see that BlockingCollection requires a call to CompleteAdding, which I can't do, because I always get incoming threads (I hardcoded to 10 in the example below for debugging purposes), think web requests.
public class MyTest {
private const int MaxThreads = 3;
private BlockingCollection<string> pool;
public MyTest() {
pool = new BlockingCollection<string>(MaxThreads);
}
public void Go() {
var addSuccess = this.pool.TryAdd(string.Format("thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
if (!addSuccess) Console.WriteLine(string.Format("thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
Console.WriteLine(string.Format("Adding thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
Console.WriteLine(string.Format("Pool size: {0}", pool.Count));
// simulate work
Thread.Sleep(1000);
Console.WriteLine("Thread ID#{0} " + Thread.CurrentThread.ManagedThreadId + " is done doing work.");
string val;
var takeSuccess = this.pool.TryTake(out val);
if (!takeSuccess) Console.WriteLine(string.Format("Failed to take out thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
Console.WriteLine("Taking out " + val);
Console.WriteLine(string.Format("Pool size: {0}", pool.Count));
Console.WriteLine(Environment.NewLine);
}
}
static void Main()
{
var t = new MyTest();
Parallel.For(0, 10, x => t.Go());
}
Any ideas on how I can better achieve this?
Thanks!
P.S. Multi-threading newbie here, if you have any suggestions for reading materials, I would greatly appreciate them.
LE: Based on the answers I got, I was able to achieve the desired behavior using this algorithm:
public class MyTest {
private const int MaxThreads = 3;
private SemaphoreSlim semaphore;
public MyTest() {
semaphore = new SemaphoreSlim(MaxThreads, MaxThreads);
}
public void Go() {
Console.WriteLine(string.Format("In comes thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
semaphore.Wait();
try {
Console.WriteLine(string.Format("Serving thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
// simulate work
Thread.Sleep(1000);
Console.WriteLine(string.Format("Out goes thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
}
finally {
semaphore.Release();
}
}
}
static void Main()
{
var t = new MyTest();
Parallel.For(0, 10, x=> t.Go());
}
If you want to protect certain number of threads which can access a critical region at a time, you'll have to use Semaphore or SemaphoreSlim. I suggest latter one, which is light weight when compared to former.
One disadvantage of SemaphoreSlim is that they won't work cross process, but that's fine we have Semaphore to help.
You can test whether the Semaphore is full via one of the Wait methods provided by the framework with a timeout.
SemaphoreSlim semaphore = new SemaphoreSlim(3, 3);
if (!semaphore.Wait(0))
{
//Already semaphore full.
//Handle it as you like
}
http://www.albahari.com/threading/ is a very good resource for threading.

How can i use AutoResetEventHandler to signal Main thread function to start threads again once the first set of worker threads are done processing

Requirement :- At any given point of time only 4 threads should be calling four different functions. As soon as these threads complete, next available thread should call the same functions.
Current code :- This seems to be the worst possible way to achieve something like this. While(True) will cause unnecessary CPU spikes and i could see CPU rising to 70% when running the following code.
Question :- How can i use AutoResetEventHandler to signal Main thread Process() function to start next 4 threads again once the first 4 worker threads are done processing without wasting CPU cycles. Please suggest
public class Demo
{
object protect = new object();
private int counter;
public void Process()
{
int maxthread = 4;
while (true)
{
if (counter <= maxthread)
{
counter++;
Thread t = new Thread(new ThreadStart(DoSomething));
t.Start();
}
}
}
private void DoSomething()
{
try
{
Thread.Sleep(50000); //simulate long running process
}
finally
{
lock (protect)
{
counter--;
}
}
}
You can use TPL to achieve what you want in a simpler way. If you run the code below you'll notice that an entry is written after each thread terminates and only after all four threads terminate the "Finished batch" entry is written.
This sample uses the Task.WaitAll to wait for the completion of all tasks. The code uses an infinite loop for illustration purposes only, you should calculate the hasPendingWork condition based on your requirements so that you only start a new batch of tasks if required.
For example:
private static void Main(string[] args)
{
bool hasPendingWork = true;
do
{
var tasks = InitiateTasks();
Task.WaitAll(tasks);
Console.WriteLine("Finished batch...");
} while (hasPendingWork);
}
private static Task[] InitiateTasks()
{
var tasks = new Task[4];
for (int i = 0; i < tasks.Length; i++)
{
int wait = 1000*i;
tasks[i] = Task.Factory.StartNew(() =>
{
Thread.Sleep(wait);
Console.WriteLine("Finished waiting: {0}", wait);
});
}
return tasks;
}
One other thing, from the textual requirement section on your question I'm lead to believe that a batch of four new threads should only start after all previously four threads completed. However the code you posted is not compatible with that requirement, since it starts a new thread immediately after a previous thread terminate. You should clarify what exactly is your requirement.
UPDATE:
If you want to start a thread immediately after one of the four threads terminate you can still use TPL instead of starting new threads explicitly but you can limit the number of running threads to four by using a SemaphoreSlim. For example:
private static SemaphoreSlim TaskController = new SemaphoreSlim(4);
private static void Main(string[] args)
{
var random = new Random(570);
while (true)
{
// Blocks thread without wasting CPU
// if the number of resources (4) is exhausted
TaskController.Wait();
Task.Factory.StartNew(() =>
{
Console.WriteLine("Started");
Thread.Sleep(random.Next(1000, 3000));
Console.WriteLine("Completed");
// Releases a resource meaning TaskController.Wait will unblock
TaskController.Release();
});
}
}

Synchronising threads: is there a conflict here?

class Class1
{
private static object consoleGate = new Object();
private static void Trace(string msg)
{
lock (consoleGate)
{
Console.WriteLine("[{0,3}/{1}]-{2}:{3}", Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsThreadPoolThread ? "pool" : "fore",
DateTime.Now.ToString("HH:mm:ss.ffff"), msg);
}
}
private static void ProcessWorkItems()
{
lock (consoleGate)
{
for (int i = 0; i < 5; i++)
{
Trace("Processing " + i);
Thread.Sleep(250);
}
}
Console.WriteLine("Terminado.");
}
static void Main()
{
ProcessWorkItems(); Console.ReadLine();
}
}
output:
Processing 0
Processing 1
Processing 2
Processing 3
Processing 4
Terminated
Why is this code works? ProcessWorkItems static method locks ConsoleGate object and Trace did the same. I thought the object could only be locked once. ¿Some explanations?
locks in C# are re-entrant - a single thread can acquire the same lock multiple times without blocking. Sine you only have one thread here there is no problem - locks are for synchronizing access to resources across multiple threads.
From the MSDN documentation on lock:
The lock keyword ensures that one thread does not enter a critical
section of code while another thread is in the critical section. If
another thread tries to enter a locked code, it will wait, block,
until the object is released.
For more information on re-entrant-locking see this SO thread: "What is the Re-entrant lock and concept in general?"
All the code you have displayed here is running on the same thread. That is why it is running just like it would if you hadn't used "lock"

Aborting a .NET thread

I am creating a thread A and in that thread creating a new thread B.
So how is the thread hierarchy? Thread B is child of Thread A? Or the threads are created as peers?
I want to abort the parent thread A which in turn kills/aborts its child threads.
How is that possible in C#?
Threads should ideally never be aborted. It simply isn't safe. Consider this as a way of putting down an already sick process. Otherwise, avoid like the plague.
The more correct way of doing this is to have something that the code can periodically check, and itself decide to exit.
An example of stopping threads the polite way:
using System;
using System.Threading;
namespace Treading
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Main program starts");
Thread firstThread = new Thread(A);
ThreadStateMessage messageToA = new ThreadStateMessage(){YouShouldStopNow = false};
firstThread.Start(messageToA);
Thread.Sleep(50); //Let other threads do their thing for 0.05 seconds
Console.WriteLine("Sending stop signal from main program!");
messageToA.YouShouldStopNow = true;
firstThread.Join();
Console.WriteLine("Main program ends - press any key to exit");
Console.Read();//
}
private class ThreadStateMessage
{
public bool YouShouldStopNow = false; //this assignment is not really needed, since default value is false
}
public static void A(object param)
{
ThreadStateMessage myMessage = (ThreadStateMessage)param;
Console.WriteLine("Hello from A");
ThreadStateMessage messageToB = new ThreadStateMessage();
Thread secondThread = new Thread(B);
secondThread.Start(messageToB);
while (!myMessage.YouShouldStopNow)
{
Thread.Sleep(10);
Console.WriteLine("A is still running");
}
Console.WriteLine("Sending stop signal from A!");
messageToB.YouShouldStopNow = true;
secondThread.Join();
Console.WriteLine("Goodbye from A");
}
public static void B(object param)
{
ThreadStateMessage myMessage = (ThreadStateMessage)param;
Console.WriteLine("Hello from B");
while(!myMessage.YouShouldStopNow)
{
Thread.Sleep(10);
Console.WriteLine("B is still running");
}
Console.WriteLine("Goodbye from B");
}
}
}
Using Thread.Abort(); causes an exception to be thrown if your thread is in a waiting state of any kind. This is sort of annoying to handle, since there are quite a number of ways that a thread can be waiting. As others have said, you should generally avoid doing it.
Thread.Abort will do what you want, but it is not recommended to abort thread, better choose is to think a way for finishing threads correctly by Thread synchronization mechanism
Here's yet another way to politely signal a thread to die:
Note that this fashion favors finite state automatons where the slave periodically checks for permission to live, then performs a task if allowed. Tasks are not interrupted and are 'atomic'. This works great with simple loops or with command queues. Also this makes sure the thread doesn't spin 100% cpu by giving the slave thread a rest period, set this one to 0 if you don't want any rest in your slave.
var dieEvent = new AutoResetEvent(false);
int slaveRestPeriod = 20;// let's not hog the CPU with an endless loop
var master = new Thread(() =>
{
doStuffAMasterDoes(); // long running operation
dieEvent.Set(); // kill the slave
});
var slave = new Thread(() =>
{
while (!dieEvent.WaitOne(restPeriod))
{
doStuffASlaveDoes();
}
});
slave.Start();
master.Start();
Threads are created as peers, obtain a handle to Thread A and then call ThreadA.Abort()
to forcefully end it. It's better to check a boolean in the thread and if it evaluates to false exit the thread.
public class MyClass
{
public static Thread ThreadA;
public static Thread ThreadB;
private void RunThings()
{
ThreadA = new Thread(new ThreadStart(ThreadAWork));
ThreadB = new Thread(new ThreadStart(ThreadBWork));
ThreadA.Start();
ThreadB.Start();
}
static void ThreadAWork()
{
// do some stuff
// thread A will close now, all work is done.
}
static void ThreadBWork()
{
// do some stuff
ThreadA.Abort(); // close thread A
// thread B will close now, all work is done.
}
}

Categories

Resources