My code below halts on the semaphore.
Code creates the thread correctly. It runs correctly when the semaphore code is removed.
How do I make my semaphore block the code section, this case is just a loop, then release the semaphore when the loop is done.
lock
loop
un-lock
actual code here:
using System.IO;
using System;
using System.Threading;
public class Program
{
public static Semaphore sema;
static void Main()
{
sema = new Semaphore(0, 2);
Work w = new Work();
Thread t = new Thread(w.doWork);
t.Start(null);
}
}
public class Work
{
public void doWork(object data)
{
Program.sema.WaitOne();
for(int i = 0; i < 10; i++)
Console.WriteLine("I made it");
Program.sema.Release();
}
}
The semaphore is initially closed because there are no free slots available. There must be some free before you are able to cross the WaitOne() call.
sema = new Semaphore(0, 2);
This is allowing 0 enters, you need to modify 0 to the number of concurrent access you want to allow.
Related
My requirement is to handle a thread from a different thread. I am able to do with thread.Suspend(), thread.Resume() and thread.Abort() but I am getting a warning like these methods has been deprecated. Is there any alternative to these methods, I created a dummy console application which is similar to my application please help to to fix this.
Below is my code
using System;
using System.Threading;
namespace ThreadingTest
{
internal class Program
{
private static Thread mainThread;
private static void Main(string[] args)
{
mainThread = Thread.CurrentThread;
Thread connectServerThread = new Thread(new ThreadStart(ConnectServer));
connectServerThread.Start();
int i = 0;
while (true)
{
if (i++ % 5000 == 0)
{
Console.WriteLine(i);
}
}
}
private static void ConnectServer()
{
for (int i = 0; i < 20; i++)
{
Thread.Sleep(2000);
if (i % 2 == 0)
{
mainThread.Suspend();
}
else
{
mainThread.Resume();
}
}
mainThread.Abort();
}
}
}
I would follow the advice in the documentation
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.
And more specifically, the advice the warning provides:
Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources
I am using two threads in a C# application that access the same BlockingCollection. This works fine, but I want to retrieve the first value twice so the two threads retrieve the same value *.
After a few seconds I want to poll the currentIndex of both threads and delete every value < index. So for example the lowest currentIndex of a thread is 5, the application deletes theitems at index 0 -5 in the queue. Another solution is to delete the value in the queue if all threads processed the value.
How can I accomplish this? I think I need another type of buffer..?
Thank you in advance!
*If .Take() is called by thread1, the item is removed in the collection and thread2 can't get the same item again.
Update:
I want to store data in a buffer, so for example thread1 saves the data to a HDD and thread2 analyzes the (same) data (concurrent).
Use a producer-consumer to add Value1 to two separate ConcurrentQueues. Have the threads dequeue then process them from their own queue.
Edit 7/4/14:
Here's a, hazy, hacky, and half thought out solution: Create a custom object that is buffered. It could include space for both the information you're trying to buffer in thread 1 and the analysis results in thread 2.
Add the objects to a buffer in thread 1 and a BlockingCollection. Use thread 2 to analyse the results and update the objects with the results. The blocking collection shouldn't get too big, and since it's only dealing with references shouldn't hit your memory. This assumes that you won't be modifying the info in the buffer at the same time on both threads.
Another, also half thought out solution is to feed the info into the buffer and a blocking collection simultaneously. Analyse the data from the BlockingCollection, feed it into an output collection and match them up with the buffer again. This option can handle concurrent modification if you do it right, but is probably more work.
I think option one is better. As I've pointed out, these are only half-formed, but they might help you find something that suits your specific needs. Good luck.
I would suggest to rethink your design.
When you have a list of items which have to processed then give each thread a queue of items which he have to work on.
With such a solution it wouldn't be a problem to give both or more threads the same value to process.
Something like this, not tested just typed.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections.Concurrent;
namespace ConsoleApplication2
{
class Item
{
private int _value;
public int Value
{
get
{
return _value;
}
}
// all you need
public Item(int i)
{
_value = i;
}
}
class WorkerParameters
{
public ConcurrentQueue<Item> Items = new ConcurrentQueue<Item>();
}
class Worker
{
private Thread _thread;
private WorkerParameters _params = new WorkerParameters();
public void EnqueueItem(Item item)
{
_params.Items.Enqueue(item);
}
public void Start()
{
_thread = new Thread(new ParameterizedThreadStart(ThreadProc));
_thread.Start();
}
public void Stop()
{
// build somthing to stop your thread
}
public static void ThreadProc(object threadParams)
{
WorkerParameters p = (WorkerParameters)threadParams;
while (true)
{
while (p.Items.Count > 0)
{
Item item = null;
p.Items.TryDequeue(out item);
if (item != null)
{
// do something
}
}
System.Threading.Thread.Sleep(50);
}
}
}
class Program
{
static void Main(string[] args)
{
Worker w1 = new Worker();
Worker w2 = new Worker();
w1.Start();
w2.Start();
List<Item> itemsToProcess = new List<Item>();
for (int i = 1; i < 1000; i++)
{
itemsToProcess.Add(new Item(i));
}
for (int i = 1; i < 1000; i++)
{
w1.EnqueueItem(itemsToProcess[i]);
w2.EnqueueItem(itemsToProcess[i]);
}
}
}
}
I am trying to implement a multithreaded library that would run simultaneous tasks using threadpool. Basically it will add tasks to threadpool from the collection parameter it receive and then will wait until last task that is being processed sends a pulse signal. I had success in my earlier tests but I encountered a weird issue when I wanted to test with tasks that are really short to process. Somehow either pulse signal is sent before wait command takes in place in the main thread or something else is going on that I just can't simply see regardless of my efforts for syncronization.
In order to remediate my problem I have implemented another "less desirable" solution because of the potential performance benefits I am trading off which is working well as of now, but wanted to know why my first approach doesn't work in such cases in the first place even though performance wise there are not much of a difference between the two.
To illustrate, I am adding both solutions after I simplified the processes below. Can someone help me to point what is going wrong?
Thanks in advance.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
namespace TestcodeBenchmark
{
class Program
{
static int remainingTasks = 10000000;
static Stopwatch casioF91W = new Stopwatch();
static Random rg = new Random();
static readonly object waitObject = new object();
static void Main(string[] args)
{
TestLoop(30, remainingTasks);
Console.ReadKey();
}
private static void TestLoop(int loopCount, int remainingCountResetNumber)
{
for (int i = 0; i < loopCount; i++)
{
remainingTasks = remainingCountResetNumber;
//When this method is called it eventualy stuck at Monitor.Wait line
TestInterlocked();
remainingTasks = remainingCountResetNumber;
//When this method is called it processes stuff w/o any issues.
TestManualLock();
Console.WriteLine();
}
}
private static void TestInterlocked()
{
casioF91W.Restart();
//for (int i = 0; i < remainingTasks; i++)
//{
// ThreadPool.QueueUserWorkItem(delegate { TestInterlockedDecrement(); });
//}
int toStart = remainingTasks;
//for (int i = 0; i < remainingTasks; i++)
for (int i = 0; i < toStart; i++)
{
if (!ThreadPool.QueueUserWorkItem(delegate { TestInterlockedDecrement(); }))
Console.WriteLine("Queue failed");
}
//lock waitObject to be able to call Monitor.Wait
lock (waitObject)
{
//if waitObject is locked then no worker thread should be able to send a pulse signal
//however, if pulse signal was sent before locking here remainingTasks should be
//zero so don't wait if all tasks are processed already
if (remainingTasks != 0)
{
//release the lock on waitObject and wait pulse signal from the worker thread that
//finishes last task
Monitor.Wait(waitObject);
}
}
casioF91W.Stop();
Console.Write("Interlocked:{0}ms ", casioF91W.ElapsedMilliseconds);
}
private static void TestInterlockedDecrement()
{
//process task
//TestWork();
//Once processing finishes decrement 1 from remainingTasks using Interlocked.Decrement
//to make sure it is atomic and therefore thread safe. If resulting value is zero
//send pulse signal to wake main thread.
if (Interlocked.Decrement(ref remainingTasks) == 0)
{
//Acquire a lock on waitObject to be able to send pulse signal to main thread. If main
//thread acquired the lock earlier, this will wait until main thread releases it
lock (waitObject)
{
//send a pulse signal to main thread to continue
Monitor.PulseAll(waitObject);
}
}
}
private static void TestManualLock()
{
casioF91W.Restart();
//Acquire the lock on waitObject and don't release it until all items are added and
//Wait method is called. This will ensure wait method is called in main thread
//before any worker thread can send pulse signal by requiring worker threads to
//lock waitObject to be able to modify remainingTasks
lock (waitObject)
{
for (int i = 0; i < remainingTasks; i++)
{
ThreadPool.QueueUserWorkItem(delegate { TestManualDecrement(); });
}
Monitor.Wait(waitObject);
}
casioF91W.Stop();
Console.Write("ManualLock:{0}ms ", casioF91W.ElapsedMilliseconds);
}
private static void TestManualDecrement()
{
//TestWork();
//try to acquire lock on wait object.
lock (waitObject)
{
//if lock is acquired, decrement remaining tasks by and then check
//whether resulting value is zero.
if (--remainingTasks == 0)
{
//send a pulse signal to main thread to continue
Monitor.PulseAll(waitObject);
}
}
}
private static void TestWork()
{
//Uncomment following to simulate some work.
//int i = rg.Next(100, 110);
//for (int j = 0; j < i; j++)
//{
//}
}
}
}
When you start your tasks, you loop is starting remainingTasks tasks. By the time you near 10000, however, some of the tasks have completed and decremented this number to less than 10000, so you do not start the proper number of tasks. If I modify your loop to save how many tasks should be started, the code runs successfully. (Note that you should also be checking the return value of QueueUserWorkItem.)
int toStart = remainingTasks;
for (int i = 0; i < toStart; i++)
{
if (!ThreadPool.QueueUserWorkItem(delegate { TestInterlockedDecrement(); }))
Console.WriteLine("Queue failed");
}
Consider the code below. I do not want to create multiple instances of class Waiter. (So I cannot use ManualResetEvent class)
using System;
using System.Threading;
public class Waiter
{
static int counter=0;
static int max=20;
public void Start()
{
for (int i = 1; i <= max; i++)
{
ThreadPool.QueueUserWorkItem(DoWork, (object)i);
}
Console.Read();//without this line the application quits before all threads are complete :(
}
public void DoWork(object o)
{
try
{
Thread.Sleep(1000);
}
finally
{
counter++;
Console.WriteLine(counter);
if (counter==max )
{
Console.WriteLine("All threads complete");
}
}
}
}
public class ThreadPoolExample
{
static void Main()
{
Waiter wtr=new Waiter();
wtr.Start();
}
}
I have two problems with the above code
1>Without the Console.Read() the application quits before all threads end.
2>The statement Console.WriteLine("All threads complete"); executes twice.
How do I fix this?
Use Tasks instead, and then you can do Task.WaitAll(tasks);
Also, instantiate your tasks through the factory:
Task.Factory.StartNew(() => { Console.Writeline(""); });
It will use the thread pool for you.
You should be using Interlocked.Increment to increment counter. As it is there is a race condition when two threads try to increment it at the same time.
If you want to have multiple instances of Writer working at the same time then you can't have a static counter variable. They'll fight with each other. Just make it a private instance variable and you should be fine. Max should either be const or readonly (and stay static) if it never changes, or it should also be an instance field if it can change.
And finally, if you have a non-static ManualResetEvent instance you can create it in Start, initialize it to set, wait for it at the end of the loop, and then signal it when the last thread finishes (where you currently just write to the console).
I'm starting with the C# code example here. I'm trying to adapt it for a couple reasons: 1) in my scenario, all tasks will be put in the queue up-front before consumers will start, and 2) I wanted to abstract the worker into a separate class instead of having raw Thread members within the WorkerQueue class.
My queue doesn't seem to dispose of itself though, it just hangs, and when I break in Visual Studio it's stuck on the _th.Join() line for WorkerThread #1. Also, is there a better way to organize this? Something about exposing the WaitOne() and Join() methods seems wrong, but I couldn't think of an appropriate way to let the WorkerThread interact with the queue.
Also, an aside - if I call q.Start(#) at the top of the using block, only some of the threads every kick in (e.g. threads 1, 2, and 8 process every task). Why is this? Is it a race condition of some sort, or am I doing something wrong?
using System;
using System.Collections.Generic;
using System.Text;
using System.Messaging;
using System.Threading;
using System.Linq;
namespace QueueTest
{
class Program
{
static void Main(string[] args)
{
using (WorkQueue q = new WorkQueue())
{
q.Finished += new Action(delegate { Console.WriteLine("All jobs finished"); });
Random r = new Random();
foreach (int i in Enumerable.Range(1, 10))
q.Enqueue(r.Next(100, 500));
Console.WriteLine("All jobs queued");
q.Start(8);
}
}
}
class WorkQueue : IDisposable
{
private Queue<int> _jobs = new Queue<int>();
private int _job_count;
private EventWaitHandle _wh = new AutoResetEvent(false);
private object _lock = new object();
private List<WorkerThread> _th;
public event Action Finished;
public WorkQueue()
{
}
public void Start(int num_threads)
{
_job_count = _jobs.Count;
_th = new List<WorkerThread>(num_threads);
foreach (int i in Enumerable.Range(1, num_threads))
{
_th.Add(new WorkerThread(i, this));
_th[_th.Count - 1].JobFinished += new Action<int>(WorkQueue_JobFinished);
}
}
void WorkQueue_JobFinished(int obj)
{
lock (_lock)
{
_job_count--;
if (_job_count == 0 && Finished != null)
Finished();
}
}
public void Enqueue(int job)
{
lock (_lock)
_jobs.Enqueue(job);
_wh.Set();
}
public void Dispose()
{
Enqueue(Int32.MinValue);
_th.ForEach(th => th.Join());
_wh.Close();
}
public int GetNextJob()
{
lock (_lock)
{
if (_jobs.Count > 0)
return _jobs.Dequeue();
else
return Int32.MinValue;
}
}
public void WaitOne()
{
_wh.WaitOne();
}
}
class WorkerThread
{
private Thread _th;
private WorkQueue _q;
private int _i;
public event Action<int> JobFinished;
public WorkerThread(int i, WorkQueue q)
{
_i = i;
_q = q;
_th = new Thread(DoWork);
_th.Start();
}
public void Join()
{
_th.Join();
}
private void DoWork()
{
while (true)
{
int job = _q.GetNextJob();
if (job != Int32.MinValue)
{
Console.WriteLine("Thread {0} Got job {1}", _i, job);
Thread.Sleep(job * 10); // in reality would to actual work here
if (JobFinished != null)
JobFinished(job);
}
else
{
Console.WriteLine("Thread {0} no job available", _i);
_q.WaitOne();
}
}
}
}
}
The worker threads are all blocking on the _q.WaitOne() call in DoWork(). Calling the thread's Join() method will deadlock, the threads never exit. You'll need to add a mechanism to signal to worker thread to exit. A ManualResetEvent, tested with WaitAny in the worker, will get the job done.
One debugging tip: get familiar with the Debug + Windows + Threads window. It lets you switch between threads and look at their call stacks. You'd have quickly found this problem by yourself.
You do a WaitOne() at the end of DoWork but you never set it after the threads start running.
Note that AutoResetEvent will go back to not set state after a 'successful' WaitOne
Your loop in your DoWork method never finishes. This will cause the thread to always be busy and this thread.Join() will block forever, waiting for it to complete.
You have a WaitOne, but I don't think it's necessary unless there is a reason you want your threadpool to stick around after your work is complete:
private void DoWork()
{
bool done = false;
while (!done)
{
int job = _q.GetNextJob();
if (job != Int32.MinValue)
{
Console.WriteLine("Thread {0} Got job {1}", _i, job);
Thread.Sleep(job * 10); // in reality would to actual work here
if (JobFinished != null)
JobFinished(job);
}
else
{
Console.WriteLine("Thread {0} no job available", _i);
done = true;
}
}
}
If you want the threads to stick around so you don't have to realloc more threads when WorkQueue.Start is called, you'd have to do something more elaborate with the AutoResetEvent.
Your main problem is the deterministic deadlock described in the other answers.
The correct way to handle it, though, is not to fix the deadlock, but to eliminate the Event altogether.
The whole idea of the Producer-Consumer model is that the clients En-queue and De-queue elements concurrently, and that's why sync mechanisms are required. If you're enqueuing all of the elements beforehand and then only dequeue concurrently, you only need a lock on the dequeue, since the "Event" is used to let "Consumers" wait for new elements to be enqueued; this will not happen in your case (based on your description).
Also, the "single responsibility" design principle suggests that the threading code should be separated from the "Blocking Queue" code. Make the "Blocking Queue" a class of its own, then use it in your thread-management class.