how threads communicate with eachother? they dont use values of eachother, then what is the way of communication between them?
There are a few ways threads can communicate with each other. This list is not exhaustive, but does include the most used strategies.
Shared memory, like a variable or some other data structure
Synchronization primitives, like locks and sempahores
Events, like ManualResetEvent or AutoResetEvent
Shared memory
public static void Main()
{
string text = "Hello World";
var thread = new Thread(
() =>
{
Console.WriteLine(text); // variable read by worker thread
});
thread.Start();
Console.WriteLine(text); // variable read by main thread
}
Synchronization primitives
public static void Main()
{
var lockObj = new Object();
int x = 0;
var thread = new Thread(
() =>
{
while (true)
{
lock (lockObj) // blocks until main thread releases the lock
{
x++;
}
}
});
thread.Start();
while (true)
{
lock (lockObj) // blocks until worker thread releases the lock
{
x++;
Console.WriteLine(x);
}
}
}
Events
public static void Main()
{
var are = new AutoResetEvent(false);
var thread = new Thread(
() =>
{
while (true)
{
Thread.Sleep(1000);
are.Set(); // worker thread signals the event
}
});
thread.Start();
while (are.WaitOne()) // main thread waits for the event to be signaled
{
Console.WriteLine(DateTime.Now);
}
}
"they don't use values of each other" - well two threads in the same process can see common variables, so that's the simples appraoch. So we use various synchronization, locking, mutices and sempahores to wait for conditions and wake up waiting threads.
In Java you use various primitives such as synchronization. You could read this tutorial
Threads can share values, they just have to be careful when doing so. In .Net the most common methods are the lock statement and the Interlocked class.
Related
I'm a Java programmer who has been asked to make some changes to C# applications. I've been working with C# for a week now, and I've finally hit a point where looking at the documentation isn't helping and I can't find solutions when I google.
In this case I have a Windows Service that processes messages that arrive in a MSMQ. When a message is received the currently listening thread picks it up and goes off to do an operation that takes a couple of seconds.
public void Start()
{
this.listen = true;
for (int i = 0; i < Constants.ThreadMaxCount; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(this.StartListening), i);
}
...
private void StartListening(Object threadContext)
{
int threadId = (int)threadContext;
threads[threadId] = Thread.CurrentThread;
PostRequest postReq;
while(this.listen)
{
System.Threading.Monitor.Enter(locker);
try
{
postReq = GettingAMessage();
}
finally
{
System.Threading.Monitor.Exit(locker);
}
}
...
}
GettingAMessage() has the following lines that listen for a message:
Task<Message> ts = Task.Factory.FromAsync<Message>
(queue.BeginReceive(), queue.EndReceive);
ts.Wait();
The problem is, when the Stop() method is called and there are no messages going into the MSMQ the threads all sit there waiting for a message. I have tried using timeouts, but that method doesn't seem elegant to me(and having switched over to the Task Factory, I'm not sure how to implement them currently). My solution to this was to add a reference of each thread to an array, so that I could cancel them. The following is called by each worker thread after being created.
threads[threadId] = Thread.CurrentThread;
and then supposed to be aborted by
public void Stop()
{
try
{
this.listen = false;
foreach(Thread a in threads) {
a.Abort();
}
}
catch
{...}
}
Any advice on why this isn't shutting the threads down? (Or even better, can anyone tell me where I should look for how to cancel the ts.Wait() properly?)
Use the ManualResetEvent class to achieve a proper & graceful stopping of your running threads.
In addition, don't use the ThreadPool for long running threads, use your own created threads, otherwise, with lots of long-running tasks, you could end up with thread-pool starvation, possibly even leading to deadlock:
public class MsmqListener
{
privatec ManualResetEvent _stopRequested = new ManualResetEvent(false);
private List<Thread> _listenerThreads;
private object _locker = new _locker();
//-----------------------------------------------------------------------------------------------------
public MsmqListener
{
CreateListenerThreads();
}
//-----------------------------------------------------------------------------------------------------
public void Start()
{
StartListenerThreads();
}
//-----------------------------------------------------------------------------------------------------
public void Stop()
{
try
{
_stopRequested.Set();
foreach(Thread thread in _listenerThreads)
{
thread.Join(); // Wait for all threads to complete gracefully
}
}
catch( Exception ex)
{...}
}
//-----------------------------------------------------------------------------------------------------
private void StartListening()
{
while( !_stopRequested.WaitOne(0) ) // Blocks the current thread for 0 ms until the current WaitHandle receives a signal
{
lock( _locker )
{
postReq = GettingAMessage();
}
...
}
//-----------------------------------------------------------------------------------------------------
private void CreateListenerThreads()
{
_listenerThreads = new List<Thread>();
for (int i = 0; i < Constants.ThreadMaxCount; i++)
{
listenerThread = new Thread(StartListening);
listenerThreads.Add(listenerThread);
}
}
//-----------------------------------------------------------------------------------------------------
private void StartListenerThreads()
{
foreach(var thread in _listenerThreads)
{
thread.Start();
}
}
}
UPDATE:
I changed the use of AutoResetEvent with ManualResetEvent in order to support the stopping of multiple waiting threads (Using ManualResetEvent, once you signaled, all waiting threads will be notified and be free to proceed theirs job - stop pooling for messages, in your case).
Using volatile bool does not provide all the guaranties. It may still read stale data. Better to use underlying OS synchronisation mechanism as it provides much stronger guaranties. Source: stackoverflow.com/a/11953661/952310
This is my code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication4
{
class Writer {
public void Write(string xxx) { Console.Write(xxx); }
}
class Program
{
static Writer wrt;
static void Main(string[] args)
{
wrt = new Writer();
Thread trd = new Thread(new ThreadStart(delegate() {
lock (wrt)
{
Thread.Sleep(1000);
wrt.Write("1");
}
}));
trd.Start();
wrt.Write("0");
Console.ReadLine();
}
}
}
The excepted output is "10", but the output is "01". Why?
You need to lock in both places:
wrt = new Writer();
Thread trd = new Thread(new ThreadStart(delegate() {
lock (wrt)
{
Thread.Sleep(1000);
wrt.Write("1");
}
}));
trd.Start();
lock(wrt) // Lock here, too
{
wrt.Write("0");
}
Console.ReadLine();
Using a lock doesn't prevent that instance from being used other places, it just prevents that instance from being used to acquire another lock until your lock is done.
Instead of thinking of lock as "locking the object", think of it as your object is the one and only key for that lock - no other lock(yourObject) can "unlock" that block of code until the first one is done.
Note that this will still likely show "01" as output, as it's very unlikely that the thread will startup quickly enough to get the lock first, but that's not deterministic.
Why not use Tasks? It will ensure that the first thread is complete before continuing with the next thread.
class Program
{
static void Main(string[] args)
{
var writer = new Writer();
var task = Task.Factory.StartNew(() =>
{
writer.Write("1");
});
task.ContinueWith((data) =>
{
writer.Write("0");
});
Console.ReadKey();
}
}
public class Writer
{
public void Write(string message)
{
Console.Write(message);
}
}
The statement wrt.Write("0"); in the main thread is executed before the trd thread. The main thread starts the trd thread and keeps executing the statements those come under main thread thats why the Write statement under main thread is executing before trd thread.
The lock statement is inside trd thread and thus has nothing to do with wrt.Write under main thread. You can put lock on main thread as Reed Copsey suggested but you can not ensure which thread will get lock first. It could be main thread which gets the lock first.
You can ensure the trd thread finsishes execution prior to main thread by calling Thread.Join after starting thread trd, it will ensure main thread will wait until trd thread finishes the exectuion. This will ensure that you get 10 instead of 01.
static Writer wrt;
static void Main(string[] args)
{
wrt = new Writer();
Thread trd = new Thread(new ThreadStart(delegate() {
lock (wrt)
{
Thread.Sleep(1000);
wrt.Write("1");
}
}));
trd.Start();
trd.Join();
wrt.Write("0");
Console.ReadLine();
}
I'm trying to implement an algorithm that should run in parallel using threads or tasks. The difficulty is that I want the threads/tasks to share their best results from time to time with all other threads.
The basic idea is this:
//Accessible from each thread
IProducerConsumerCollection<MyObject> _bestObjects;
//Executed in each thread
DoSomeWork(int n){
MyObject localObject;
for(var i = 0; i < n; i++){
//Do some calculations and store results in localObject
if((i/n)%0.5 == 0)
{
//store localObject in _bestObjects
//wait until each thread has stored its result in _bestObjects
//get the best result from _bestObjects and go on
}
}
}
How can this be achieved using System.Threading or System.Threading.Tasks and is it true that tasks should not be used for long running operations?
Update: Clarification
It's not my problem to have a thread safe collection but to make the threads stop, publish result, wait until all other threads have publihed their results to and then go on again. All threads will run simultaneously.
Cutting a long story short:
Whats better for long running operations? Task or Thread or anything else?
How to communicate between threads/taks to inform each of them about the state of all other assuming that the number of threads is set at runtime (depending on available cores).
Best Regards
Jay
Look at the dollowing example.
public class Worker
{
public SharedData state;
public void Work(SharedData someData)
{
this.state = someData;
while (true) ;
}
}
public class SharedData {
X myX;
public getX() { ... }
public setX(anX) { ... }
}
public class Sharing
{
public static void Main()
{
SharedData data = new SharedDate()
Worker work1 = new Worker(data);
Worker work2 = new Worker(data);
Thread thread = new Thread(new ThreadStart(work1.Work));
thread.start();
Thread thread2 = new Thread(new ThreadStart(work2.Work));
thread2.start();
}
}
bomslang's response is not accurate. Cannot instantiate a new thread with ThreadStart, passing in Work method which requires a parameter to be passed in the above example. ParameterizedThreadStart would be more suitable. The sample code for the Main method would look more like this:
public class Sharing
{
public static void Main()
{
SharedData data = new SharedDate()
Worker work1 = new Worker(data);
Worker work2 = new Worker(data);
Thread thread = new Thread(new ParameterizedThreadStart(work1.Work));
thread.start(someData);
Thread thread2 = new Thread(new ParameterizedThreadStart(work2.Work));
thread2.start(someData);
}
}
Note that 'work' is being passed into the ParameterizedThreadStart as the method for the new thread to execute, and the data required to pass in to the 'work' method is being passed in the call to start. The data must be passed as an object, so the work method will need to cast it back to the appropriate datatype as well. Lastly, there is also another approach to passing in data to a new thread via the use of anonymous methods.
I work with new Parallel.For that creates multiple threads to perform the same operation.
In case one of the threads fail, it means that I'm working "too fast" and I need to put all the threads to rest for a few seconds.
Is there a way to perform something like Thread.Sleep - only to do the same on all threads at once?
This is a direct answer to the question, except for the Parallel.For bit.
It really is a horrible pattern; you should probably be using a proper synchronization mechanism, and get the worker threads to, without preemption, occasionally check if they need to 'back off.'
In addition, this uses Thread.Suspend and Thread.Resume which are both deprecated, and with good reason (from Thread.Suspend):
"Do not use the Suspend and Resume methods to synchronize the activities of threads. You have no way of knowing what code a thread is executing when you suspend it. If you suspend a thread while it holds locks during a security permission evaluation, other threads in the AppDomain might be blocked. If you suspend a thread while it is executing a class constructor, other threads in the AppDomain that attempt to use that class are blocked. Deadlocks can occur very easily."
(Untested)
public class Worker
{
private readonly Thread[] _threads;
private readonly object _locker = new object();
private readonly TimeSpan _tooFastSuspensionSpan;
private DateTime _lastSuspensionTime;
public Worker(int numThreads, TimeSpan tooFastSuspensionSpan)
{
_tooFastSuspensionSpan = tooFastSuspensionSpan;
_threads = Enumerable.Repeat(new ThreadStart(DoWork), numThreads)
.Select(ts => new Thread(ts))
.ToArray();
}
public void Run()
{
foreach (var thread in _threads)
{
thread.Start();
}
}
private void DoWork()
{
while (!IsWorkComplete())
{
try
{
// Do work here
}
catch (TooFastException)
{
SuspendAll();
}
}
}
private void SuspendAll()
{
lock (_locker)
{
// We don't want N near-simultaneous failures causing a sleep-duration of N * _tooFastSuspensionSpan
// 1 second is arbitrary. We can't be deterministic about it since we are forcefully suspending threads
var now = DateTime.Now;
if (now.Subtract(_lastSuspensionTime) < _tooFastSuspensionSpan + TimeSpan.FromSeconds(1))
return;
_lastSuspensionTime = now;
var otherThreads = _threads.Where(t => t.ManagedThreadId != Thread.CurrentThread.ManagedThreadId).ToArray();
foreach (var otherThread in otherThreads)
otherThread.Suspend();
Thread.Sleep(_tooFastSuspensionSpan);
foreach (var otherThread in otherThreads)
otherThread.Resume();
}
}
}
You need to create an inventory of your worker threads and then perhaps you can use Thread.Suspend and Resume methods. Mind you that using Suspend can be dangerous (for example, thread may have acquired lock before suspending). And suspend/resume have been marked obsolate due to such issues.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C# Spawn Multiple Threads for work then wait until all finished
I have two method calls that I want to call using two threads. Then I want them to wait till method executions get completed before continuing. My sample solution is something like below.
public static void Main()
{
Console.WriteLine("Main thread starting.");
String[] strThreads = new String[] { "one", "two" };
String ctemp = string.Empty;
foreach (String c in strThreads)
{
ctemp = c;
Thread thread = new Thread(delegate() { MethodCall(ctemp); });
thread.Start();
thread.Join();
}
Console.WriteLine("Main thread ending.");
Console.Read();
}
public static void MethodCalls(string number)
{
Console.WriteLine("Method call " + number);
}
Is this will do the job? Or is there another better way to do the same thing?
I'd look into running your method via ThreadPool.QueueUserWorkItem and then using WaitHandle.WaitAll to wait for all of them to complete.
This sequence of statements...:
Thread thread = new Thread(delegate() { MethodCall(ctemp); });
thread.Start();
thread.Join();
is equivalent to just calling the method directly -- since you're waiting for the new thread to finish right after starting it, there's no benefit from threading! You need to first start all threads in a loop (put them in an array list or some similar container), then join them in a separate loop, to get concurrent execution of the methods.
What you're doing ther eis creating a thread and then waiting to finish, one by one. You have, at any time, at most two thread running: the main and the one started.
What you want is to start all threads, then wait for all to complete:
public static void Main()
{
Console.WriteLine("Main thread starting.");
String[] strThreads = new String[] { "one", "two" };
int threadCount = strThreads.Length;
AutoResetEvent eventdone = new AutoResetEvent(false);
String ctemp = string.Empty;
foreach (String c in strThreads)
{
ctemp = c;
Thread thread = new Thread(delegate() {
try
{
MethodCall(ctemp);
}
finally
{
if (0 == Interlocked.Decrement(ref threadCount)
{
eventDone.Set();
}
}
});
thread.Start();
}
eventDone.WaitOne();
Console.WriteLine("Main thread ending.");
Console.Read();
}
public static void MethodCalls(string number)
{
Console.WriteLine("Method call " + number);
}
If you intended for your two threads to execute one after the other, then yes, the above code will suffice (though my C# syntax knowledge is a little fuzzy off the top of my head so I can't say if the above compiles nicely or not), but why use threads if you want ordered, synchronous execution?
If instead what you want is for the two method calls to execute in parallel, you need to take the thread.Join(); out of the for-loop (you'll need to hang on to the thread objects, likely in an array.)
Take a look at BackgroundWorker Component; I beleive it works with Windows Forms, WPF and Silverlight, basically somewhere UI is involved