Below code is not working usin Auto Reset event, what wrong i am doing ?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Threaddd
{
class Program
{
static int num = 0;
static EventWaitHandle e = new AutoResetEvent(false);
static object o = new object();
static void Main(string[] args)
{
new Thread(Consumer).Start();
new Thread(Producer).Start();
}
static void Producer()
{
while (true)
{
if (num == 0)
{
num++;
Console.WriteLine("Produced " + num);
Thread.Sleep(1000);
e.Set();
e.WaitOne();
}
}
}
static void Consumer()
{
while (true)
{
if (num == 1)
{
Console.WriteLine("Consumed " + num);
Thread.Sleep(1000);
num--;
e.Set();
e.WaitOne();
}
else
{
e.WaitOne();
}
}
}
}
It looks like when the Producer thread calls e.Set(), it does not notify the Consumer thread immediately, so the Producer thread consumes the event when it calls e.WaitOne().
From http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
"There is no guarantee that every call to the Set method will release a thread. If two calls are too close together, so that the second call occurs before a thread has been released, only one thread is released. It is as if the second call did not happen. Also, if Set is called when there are no threads waiting and the AutoResetEvent is already signaled, the call has no effect."
One idea would be to use a separate event for each thread as the supplied link illustrates.
This is not a real consumer / producer pattern implementation.
e.Set() will release only ONE thread that is waiting using e.WaitOne()
So, when you write:
e.Set();
e.WaitOne();
On the producer thread, you are actually not enabling the consumer thread to get the signal
Try the following:
static void Producer()
{
while (true)
{
Thread.Sleep(1000);
Console.WriteLine("Produced " + num++);
e.Set();
}
}
static void Consumer()
{
while (true)
{
e.WaitOne();
Console.WriteLine("Consumed " + num);
}
}
If your okay with your consumer and producer thread running wild you can simplify your program by removing some of the sets and waitones:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Threaddd
{
internal class Program
{
private static int num = 0;
private static EventWaitHandle e = new AutoResetEvent(false);
private static object o = new object();
private static void Main(string[] args)
{
new Thread(Consumer).Start();
new Thread(Producer).Start();
}
private static void Producer()
{
while (true)
{
if (num == 0)
{
num++;
Console.WriteLine("Produced " + num);
Thread.Sleep(1000);
e.Set();
}
}
}
private static void Consumer()
{
while (true)
{
if (num == 1)
{
Console.WriteLine("Consumed " + num);
Thread.Sleep(1000);
num--;
e.WaitOne();
}
}
}
}
}
If that is not an option both your producer and consumer(s) must have their own events.
To keep num between 0 and 1 you can use the following pattern and lose the if statements:
class Program
{
static volatile int num = 0;
// Initialized set to ensure that the producer goes first.
static EventWaitHandle consumed = new AutoResetEvent(true);
// Initialized not set to ensure consumer waits until first producer run.
static EventWaitHandle produced = new AutoResetEvent(false);
static void Main(string[] args)
{
new Thread(Consumer).Start();
new Thread(Producer).Start();
}
static void Producer()
{
while (true)
{
consumed.WaitOne();
num++;
Console.WriteLine("Produced " + num);
Thread.Sleep(1000);
produced.Set();
}
}
static void Consumer()
{
while (true)
{
produced.WaitOne();
Console.WriteLine("Consumed " + num);
Thread.Sleep(1000);
num--;
consumed.Set();
}
}
}
It is worth pointing out that normally there is some kind of queue between the producer and the consumer so that the producer can create more than one item between each run of the consumer. The way I have written the above there is little point having the consumer and producer on separate threads as they will not be able to run at the same time.
Related
I am creating a custom CountdownWaitHandle class it has the following method:
public void Signal()
{
if (Interlocked.Decrement(ref threadsInstances) <= 0)
{
mre.Set();
}
}
mre is a instance of ManualResetEvent class and I use this class to block the current thread and wait to all threads complete his work and each thread when finish his work or occurred an exception call Signal() method.
So my question if the return value of Interlock.Decrement and condition(<=0) could cause any Concurrency Issue inside if condition? or I have to use a lock statement for the if condition and if body instead of Interlock like as example above:
lock(_lock)
{
if (--threadsInstances <= 0)
{
mre.Set();
}
}
Note:I am using 3.5 net.
Complete code:
public class CountdownWaitHandle : WaitHandle
{
private int threadsInstances = 0;
private ManualResetEvent mre;
private readonly object threadsyncAccess = new object();
public CountdownWaitHandle(int initialCount)
{
threadsInstances = initialCount;
mre = new ManualResetEvent(false);
}
public void AddCount()
{
Interlocked.Increment(ref threadsInstances);
}
public void Signal()
{
if (Interlocked.Decrement(ref threadsInstances) <= 0)
{
mre.Set();
}
}
public override bool WaitOne()
{
return mre.WaitOne();
}
}
In this example.
I am going to use my custom CountdownEvent class to download a large
file using chunks for any Cloud Site. So each chunk after finish downloading his range bytes it release the resources or move to another Stream.
public static void Main(String[] args)
{
CountdownWaitHandle customCountDown = new CountdownWaitHandle(0)
while (i < 100)
{
SpecificWork work1 = new SpecificWork (startPosition, endPosition, customCountDown);
customCountDown.AddCount();
ThreadPool.QueueUserWorkItem(PerformTask, work1); // after finish download it invokes to Signal method.
}
customCountDown.WaitOne();
}
Interlocked.Decrement will work as intended in this sample, assuming you are calling Interlocked.Increment to raise the count above zero.
Of course, using CountdownEvent would be better than building your own synchronization object.
The question is that, what happens to a thread when the function has already been executed and the thread is started in that function. (please see an example below)
public int Intialise ()
{
int i = startServer();
Thread readall = new Thread(readAllMessage);
if (i == 1)
readall.Start();
else
MessageBox.Show("Connection Error");
return i;
}
I want 'readall' to continue (forever or till the application is closed) even if the function is executed. Is it possible? Because for me the thread stops immediately even when the true condition is met. Please shed some light.
OK, here is your code slightly modified to include the loop.
internal class Program
{
public static int Intialise()
{
int i = startServer();
Thread readall = new Thread(readAllMessage);
readall.IsBackground = true; // so that when the main thread finishes, the app closes
if (i == 1)
readall.Start();
else
Console.WriteLine("Error");
return i;
}
public static void readAllMessage()
{
while (true)
{
Console.WriteLine("reading...");
Thread.Sleep(500);
}
}
public static int startServer()
{
return 1;
}
private static void Main(string[] args)
{
var i = Intialise();
Console.WriteLine("Init finished, thread running");
Console.ReadLine();
}
}
when you run it, it will print:
Init finished, thread running
reading...
reading...
reading...
and when you press enter (see Console.ReadLine()) it will stop running.
If you change the IsBackground to TRUE it would not exit the process.
Here is an example of what you ask
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ForeverApp
{
class SomeObj
{
public void ExecuteForever()
{
while (true)
{
Thread.Sleep(1000);
Console.Write(".");
}
}
}
class Program
{
static void Main(string[] args)
{
SomeObj so = new SomeObj();
Thread thrd = new Thread(so.ExecuteForever);
thrd.Start();
Console.WriteLine("Exiting Main Function");
}
}
}
Is there anything except for Mutex to synchronise two processes in a fault-tolerant fashion? Please bear with me...
There is a process A, it's a bit flaky, it needs to start process B in the background and continue. If process A successfully does its thing, it needs to signal process B to dispose, and moves on (it doesn't terminate and thread is reused). If process A dies due to exception, termination, etc. process B needs to detect it quickly and dispose of itself on its own. Process A is not a "process" rather a library executed by various hosts hence process B can't just wait for process A's name to disappear.
Enter Mutex.
Here process A represented by a test fixture, if successful it'll call TestFixtureTearDown and move on, or test runner might be killed and TestFixtureTearDown is never executed. As with the actual process, TestFixtureTearDown might be called by a different thread to one that ran TestFixtureSetUp and created the mutex, hence ReleaseMutex sometimes throws ApplicationException : Object synchronization method was called from an unsynchronized block of code.
Can I force ReleaseMutex in TestFixtureTearDown if it's being executed by a different thread or abandon mutex some other way?
Is there an alternative to Mutex that I can use for such fault-tolerant "reverse" wait/monitor scenario? Preferably without implementing process A sending heartbeats to process B and process B tracking intervals and timing out? Mutex felt like such an elegant solution except for occasional ApplicationException on asyncs.
.
namespace ClassLibrary1
{
public class Class1
{
private Mutex _mutex;
private Process _process;
[TestFixtureSetUp]
public void TestFixtureSetUp()
{
_mutex = new Mutex(true, "foo");
_process = Process.Start("ConsoleApplication1.exe");
}
[Test]
public void Test1() { /* Do stuff */ }
[Test]
public void Test2() { /* Do async stuff */ }
[TestFixtureTearDown]
public void TestFixtureTearDown()
{
_mutex.ReleaseMutex();
_process.WaitForExit();
}
}
}
.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var mutex = Mutex.OpenExisting("foo");
// Start doing stuff
try { mutex.WaitOne(); }
catch (AbandonedMutexException) { }
finally { mutex.ReleaseMutex(); }
// Finish doing stuff
}
}
}
Semaphores do not have thread affinity. You can release a semaphore on a different thread than it was acquired on. Use a semaphore with a count of 1.
I ended up using a mix of Mutex, Thread and ManualResetEvent. For the googling folk of the future here's a verbose test:
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
namespace MutexResetEvent.Tests
{
public class Class1
{
private Mutex _mutex;
private Thread _thread;
private Process _process;
private ManualResetEvent _event;
[SetUp]
public void SetUp()
{
Console.WriteLine("SetUp: #{0}", Thread.CurrentThread.ManagedThreadId);
_event = new ManualResetEvent(false);
_thread = new Thread(() =>
{
Console.WriteLine("Thread: #{0}", Thread.CurrentThread.ManagedThreadId);
_mutex = new Mutex(true, "MutexResetEvent");
_process = new Process
{
StartInfo =
{
FileName = "MutexResetEvent.Worker.exe",
//UseShellExecute = false,
//RedirectStandardOutput = true
}
};
//_process.OutputDataReceived += (o, a) => Console.WriteLine(a.Data);
_process.Start();
//_process.BeginOutputReadLine();
while (!_event.WaitOne(1000))
Console.WriteLine("Thread: ...");
Console.WriteLine("Thread: #{0}", Thread.CurrentThread.ManagedThreadId);
_mutex.ReleaseMutex();
_process.WaitForExit();
});
}
[Test]
public void Test()
{
Console.WriteLine("Test: #{0}", Thread.CurrentThread.ManagedThreadId);
_thread.Start();
for (var i = 0; i < 3; i++)
{
Console.WriteLine("Test: ...");
Thread.Sleep(1000);
}
/*
if (Guid.NewGuid().GetHashCode() % 3 == 0)
Environment.Exit(1);
//*/
}
[TearDown]
public void TearDown()
{
Console.WriteLine("TearDown: #{0}", Thread.CurrentThread.ManagedThreadId);
Task.Run(() =>
{
Console.WriteLine("Task: #{0}", Thread.CurrentThread.ManagedThreadId);
_event.Set();
//_thread.Join();
}).Wait();
for (var i = 0; i < 3; i++)
{
Console.WriteLine("TearDown: ...");
Thread.Sleep(1000);
}
}
}
}
.
using System;
using System.Threading;
namespace MutexResetEvent.Worker
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Worker: #{0}", Thread.CurrentThread.ManagedThreadId);
var mutex = Mutex.OpenExisting("MutexResetEvent");
try
{
while (!mutex.WaitOne(1000))
Console.WriteLine("Worker: ...");
}
catch (AbandonedMutexException)
{
Console.WriteLine("Worker: AbandonedMutexException");
}
Console.WriteLine("Worker: #{0}", Thread.CurrentThread.ManagedThreadId);
mutex.ReleaseMutex();
Console.WriteLine("Worker: WOO HOO");
Console.ReadLine();
}
}
}
I need a certain bit of code to wait for an item to be added to a collection. The thread itself needs to wait until this completes before it continues. The item gets added to the collection from another thread (kicked off from elsewhere), and I have no way to signal the current thread that this has occurred.
A naive implementation might look something like (ignoring thread safety on the collection, etc. for now):
public static List<string> myList = new List<string>();
public void WaitingMethod(string id)
{
bool waiting = true;
while (waiting)
{
int index = myList.IndexOf(id);
if (index >= 0)
{
waiting = false;
}
}
//thread continues here
}
I believe this would block the thread and peg the processor.
What would be a more efficient way to achieve this?
Could you instead use an observable collection, and subscribe to CollectionChanged event?
namespace ConsoleApplication3
{
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
internal class Program
{
private static readonly ObservableCollection<string> MyList = new ObservableCollection<string>();
private static AutoResetEvent resetEvent = new AutoResetEvent(false);
private static void Main(string[] args)
{
Task.Factory.StartNew(
() =>
{
for (int i = 0; i < 10; i++)
{
string item = i.ToString("0000");
MyList.Add(item);
Console.WriteLine(item);
Thread.Sleep(1000);
}
});
MyList.CollectionChanged += (sender, eventArgs) =>
{ if (eventArgs.NewItems.Cast<string>().Any(a => a.Equals("0005"))) resetEvent.Set(); };
resetEvent.WaitOne();
}
}
}
Here is how you can also control the loop generating the items being added to the collection:
namespace ConsoleApplication3
{
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
internal class Program
{
#region Static Fields
private static readonly CancellationTokenSource Cts = new CancellationTokenSource();
private static readonly ObservableCollection<string> MyList = new ObservableCollection<string>();
private static readonly AutoResetEvent ResetEvent = new AutoResetEvent(false);
#endregion
#region Methods
private static void Main(string[] args)
{
Task task = Task.Factory.StartNew(
() =>
{
for (int i = 0; i < 10 && !Cts.IsCancellationRequested; i++)
{
string item = i.ToString("0000");
MyList.Add(item);
Console.WriteLine(item);
Thread.Sleep(100);
}
},
Cts.Token);
Task finish = task.ContinueWith(antecedent => { Console.WriteLine("Task finished. Status {0}", antecedent.Status); });
MyList.CollectionChanged += (sender, eventArgs) =>
{
if (eventArgs.NewItems.Cast<string>().Any(a => a.Equals("0005")))
{
Cts.Cancel();
ResetEvent.Set();
}
};
ResetEvent.WaitOne();
Task.WaitAll(finish);
}
#endregion
}
}
As the others have said, use ObservableCollection. But, you also need an AutoResetEvent:
In the class, during instantiation or program initialization, you register a Collection Changed event handler with the ObservableCollection. When this method is called, it calls the AutoResetEvent's Set method to signal that the collection was changed.
When your thread gets to the point that it needs to wait, you wait for the AutoResetEvent.
Your other thread does its thing and changes the collection. That calls the method you registered with the collection, which raises the AutoResetEvent. That signals your thread that's waiting to wake up.
This way, the thread that's waiting has no impact on the CPU.
Scenario
I have a background worker in my application that runs off and does a bunch of processing. I specifically used this implementation so as to keep my User Interface fluid and prevent it from freezing up. I want to keep the background worker, but inside that thread, spawn off ONLY 3 MORE threads - making them share the processing (currently the worker thread just loops through and processes each asset one-by-one. However I would like to speed this up but using only a limited number of threads.
Question
Given the code below, how can I get the loop to choose a thread that is free, and then essentially wait if there isn't one free before it continues.
CODE
foreach (KeyValuePair<int, LiveAsset> kvp in laToHaganise)
{
Haganise h = new Haganise(kvp.Value,
busDate,
inputMktSet,
outputMktSet,
prodType,
noOfAssets,
bulkSaving);
h.DoWork();
}
Thoughts
I'm guessing that I would have to start off by creating 3 new threads, but my concern is that if I'm instantiating a new Haganise object each time - how can I pass the correct "h" object to the correct thread.....
Thread firstThread = new Thread(new ThreadStart(h.DoWork));
Thread secondThread =new Thread(new ThreadStart(h.DoWork));
Thread thirdThread = new Thread(new ThreadStart(h.DoWork));
Help greatly appreciated.
Depending on the size of the job the thread has to do, ThreadPool.QueueUserWorkItem may be a good option. That will create a thread and put it in a queue and execute it when there is thread in the pool available.
Alternatively you could create your own type of Pool which has 3 threads and use ManualResetEvent to determine when a particular thread is finished.
Two possibilities:
Use the ThreadPool.QueueUserWorkItem (as already mentioned by James)
Implement it BackgroundWorkers on yourself (see below)
Here is a working example, that selects the next free worker:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
private static List<MyWorker> _Workers;
static void Main(string[] args)
{
_Workers = new List<MyWorker>();
for (int i = 0; i < 5; i++)
{
_Workers.Add(CreateDefaultWorker(i));
}
StartJobs(20000);
Console.ReadKey();
}
private static void StartJobs(int runtime)
{
Random rand = new Random();
DateTime startTime = DateTime.Now;
while (DateTime.Now - startTime < TimeSpan.FromMilliseconds(runtime))
{
var freeWorker = GetFreeWorker();
if (freeWorker != null)
{
freeWorker.Worker.RunWorkerAsync(new Action(() => DoSomething(freeWorker.Index, rand.Next(500, 2000))));
}
else
{
Console.WriteLine("No free worker available!");
Console.WriteLine("Waiting for free one...");
WaitForFreeOne();
}
}
}
private static MyWorker GetFreeWorker()
{
foreach (var worker in _Workers)
{
if (!worker.Worker.IsBusy)
return worker;
}
return null;
}
private static void WaitForFreeOne()
{
while (true)
{
foreach (var worker in _Workers)
{
if (!worker.Worker.IsBusy)
return;
}
Thread.Sleep(1);
}
}
private static MyWorker CreateDefaultWorker(int index)
{
var worker = new MyWorker(index);
worker.Worker.DoWork += (sender, e) => ((Action)e.Argument).Invoke();
worker.Worker.RunWorkerCompleted += (sender, e) => Console.WriteLine("Job finished in worker " + worker.Index);
return worker;
}
static void DoSomething(int index, int timeout)
{
Console.WriteLine("Worker {1} starts to work for {0} ms", timeout, index);
Thread.Sleep(timeout);
}
}
public class MyWorker
{
public int Index { get; private set; }
public BackgroundWorker Worker { get; private set; }
public MyWorker(int index)
{
Index = index;
Worker = new BackgroundWorker();
}
}
}