I'm trying to implement AutoResetEvent. For the purpose I use a very simple class :
public class MyThreadTest
{
static readonly AutoResetEvent thread1Step = new AutoResetEvent(false);
static readonly AutoResetEvent thread2Step = new AutoResetEvent(false);
void DisplayThread1()
{
while (true)
{
Console.WriteLine("Display Thread 1");
Thread.Sleep(1000);
thread1Step.Set();
thread2Step.WaitOne();
}
}
void DisplayThread2()
{
while (true)
{
Console.WriteLine("Display Thread 2");
Thread.Sleep(1000);
thread2Step.Set();
thread1Step.WaitOne();
}
}
void CreateThreads()
{
// construct two threads for our demonstration;
Thread thread1 = new Thread(new ThreadStart(DisplayThread1));
Thread thread2 = new Thread(new ThreadStart(DisplayThread2));
// start them
thread1.Start();
thread2.Start();
}
public static void Main()
{
MyThreadTest StartMultiThreads = new MyThreadTest();
StartMultiThreads.CreateThreads();
}
}
But this is not working. Th usage seem very straight-forward so I would appreciate if someone is able to show me what's wrong and where is the problem with the logic which i implement here.
The question is not very clear but I'm guessing you're expecting it to display 1,2,1,2...
Then try this:
public class MyThreadTest
{
static readonly AutoResetEvent thread1Step = new AutoResetEvent(false);
static readonly AutoResetEvent thread2Step = new AutoResetEvent(true);
void DisplayThread1()
{
while (true)
{
thread2Step.WaitOne();
Console.WriteLine("Display Thread 1");
Thread.Sleep(1000);
thread1Step.Set();
}
}
void DisplayThread2()
{
while (true)
{
thread1Step.WaitOne();
Console.WriteLine("Display Thread 2");
Thread.Sleep(1000);
thread2Step.Set();
}
}
void CreateThreads()
{
// construct two threads for our demonstration;
Thread thread1 = new Thread(new ThreadStart(DisplayThread1));
Thread thread2 = new Thread(new ThreadStart(DisplayThread2));
// start them
thread1.Start();
thread2.Start();
}
public static void Main()
{
MyThreadTest StartMultiThreads = new MyThreadTest();
StartMultiThreads.CreateThreads();
}
}
Related
I have the below code and certainly I have a deadlock using Threads, but why not happens with tasks?
private static object lockObject1 = new object();
private static object lockObject2 = new object();
static void Main(string[] args)
{
Console.Title = "Deadlocks";
//Using tasks.
Task ourTask1 = new Task(SingleMethod_A);
ourTask1.Start();
Task ourTask2 = new Task(SingleMethod_B);
ourTask2.Start();
//Using threads.
//Thread ourThread1 = new Thread(new ThreadStart(SingleMethod_A));
//Thread ourThread2 = new Thread(new ThreadStart(SingleMethod_B));
//ourThread1.Start();
//ourThread2.Start();
Console.WriteLine("Deadlock");
}
public static void SingleMethod_A()
{
lock (lockObject1)
{
Thread.Sleep(1000);
lock (lockObject2)
{
Console.WriteLine("not possible.");
}
}
}
public static void SingleMethod_B()
{
lock (lockObject2)
{
Thread.Sleep(1000);
lock (lockObject1)
{
Console.WriteLine("not possible.");
}
}
}
Tasks can certainly dead lock. It is also important to keep in mind that Tasks aren't threads - they may run on one from the thread pool.
Why you aren't seeing it is because your case is a trivial example and .Start doesn't have to use separate threads. Try changing your calls to start to Task.Run(action) instead to see the deadlock:
Task.Run(() => SingleMethod_A());
Task.Run(() => SingleMethod_B());
Previously, I ran a method in a thread like this:
static void procedure() { while (x) thread.sleep() }
static Thread runner;
...
void method(){
runner = new Thread(new ThreadStart(procedure));
runner.Start();
}
I changed this in an attempt to have a single thread that I can start at different points.
static void procedure() { while (x) thread.sleep() }
static Thread runner;
void main(){
runner = new Thread(new ThreadStart(procedure));
...
}
...
void method(){
runner.Start();
}
This no longer runs the thread as expected. The program halts, which I believe is due to the new thread running on the main thread.
Why is it no longer running on a seperate thread?
Works fine, here's an example based on your code.
class Program
{
static void procedure()
{
while (true)
{
Thread.Sleep(1000);
Console.WriteLine("Sleep");
}
}
static Thread runner;
static void Main(string[] args)
{
runner = new Thread(new ThreadStart(procedure));
Console.WriteLine("Here!");
runner.Start();
Console.WriteLine("And now here...");
}
}
I am trying to build some kind of multi-thread game engine with reusable worker threads. That means the workers are running an endless loop and, after every iteration, call a method that suspends the thread with an AutoResetEvent until the next iteration is started from outside. Thet works fine.
But then I want to wait for all of the worker threads to get into the waiting state. But the last thread is always ignored in the first step.
This is my code:
class WorkerThread
{
private readonly Game game;
private readonly Task task;
private readonly AutoResetEvent waitEvent;
private readonly AutoResetEvent finishEvent;
public string Message { get; set; }
public bool Active { get; private set; }
public WorkerThread(Game game)
{
this.game = game;
waitEvent = new AutoResetEvent(false);
finishEvent = new AutoResetEvent(false);
task = new Task(startTask);
}
public void Start()
{
task.Start();
}
public void PerformFrame()
{
finishEvent.Reset();
waitEvent.Set();
}
public void WaitForFrameToFinish()
{
finishEvent.WaitOne();
}
private void startTask()
{
WaitFrame();
run();
}
long sum;
private void run()
{
while (true)
{
sum = 0;
for (int i = 0; i < 1000000; i++)
{
sum += i;
}
Console.WriteLine(Message);
WaitFrame();
}
}
private void WaitFrame()
{
Active = false;
finishEvent.Set();
waitEvent.WaitOne();
Active = true;
}
}
class Game
{
private readonly List<WorkerThread> workers = new List<WorkerThread>();
public Game()
{
workers.Add(new WorkerThread(this) { Message = "Worker 1" });
workers.Add(new WorkerThread(this) { Message = "Worker 2" });
workers.Add(new WorkerThread(this) { Message = "Worker 3" });
workers.Add(new WorkerThread(this) { Message = "Worker 4" });
workers.Add(new WorkerThread(this) { Message = "Worker 5" });
workers.Add(new WorkerThread(this) { Message = "Worker 6" });
}
public void Start()
{
foreach (WorkerThread worker in workers)
{
worker.Start();
}
}
public void OneFrame()
{
//start every worker
foreach (WorkerThread worker in workers)
{
worker.PerformFrame();
}
//wait for the workers to finish
foreach (WorkerThread worker in workers)
{
worker.WaitForFrameToFinish();
}
//check if there are workers still running
foreach (WorkerThread worker in workers)
{
if (worker.Active)
{
Console.WriteLine(worker.Message + " still active");
}
}
Console.WriteLine("Frame finished.\n");
}
}
Has anyone an idea why the Game doen't wait for the last WorkerThread do finish its task?
EDIT: Using a ManualResetEventSlim instead of an AutoResetEvent solves the problem. But I still don't understand why the above doesn't work.
EDIT 2: I found the answer and posted it below.
I just found the solution. startTask uses the WaitFrame method that sets the finishEvent. That way WaitForFrameToFinish will not wait for the worker on the first iteration because finishEvent is already set.
If you do it like this, it works fine:
private void startTask()
{
waitEvent.WaitOne();
waitEvent.Reset();
finishEvent.Reset();
run();
}
The scenario is as follows:
There are a couple of low priority threads that can be interrupted by high priority threads. Whenever a high priority thread asks the low priority threads to pause, they will go to Wait state (if they are not in wait state already). However when a high priority thread signals that the low priority threads can Resume, the low priority threads should not resume until all the high priority threads that asked the low priority threads to pause have consented.
To solve this I am keeping a track of Pause() calls from the high priority threads to the low priority thread in a counter variable. Whenever the high priority thread asks the low priority thread to Pause(), the value of the counter is incremented by 1. If after the increment the counter has a value of 1, it means the thread was not in Wait, so ask it to go in Wait state. Otherwise just increment counter value. On the contrary when a high priority thread calls Resume() we decrement the counter value and if after the decrement the value is 0, it means the low priority threads can Resume now.
Here is a simplified implementation of my problem. The comparison operation inside if statements with Interlocked.XXX is not correct i.e.
if (Interlocked.Increment(ref _remain) == 1)
, as the read/modify and comparison operations are not atomic.
What am I missing here? I don't want to use thread priority.
using System;
using System.Collections.Generic;
using System.Threading;
namespace TestConcurrency
{
// I borrowed this class from Joe Duffy's blog and modified it
public class LatchCounter
{
private long _remain;
private EventWaitHandle m_event;
private readonly object _lockObject;
public LatchCounter()
{
_remain = 0;
m_event = new ManualResetEvent(true);
_lockObject = new object();
}
public void Check()
{
if (Interlocked.Read(ref _remain) > 0)
{
m_event.WaitOne();
}
}
public void Increment()
{
lock(_lockObject)
{
if (Interlocked.Increment(ref _remain) == 1)
m_event.Reset();
}
}
public void Decrement()
{
lock(_lockObject)
{
// The last thread to signal also sets the event.
if (Interlocked.Decrement(ref _remain) == 0)
m_event.Set();
}
}
}
public class LowPriorityThreads
{
private List<Thread> _threads;
private LatchCounter _latch;
private int _threadCount = 1;
internal LowPriorityThreads(int threadCount)
{
_threadCount = threadCount;
_threads = new List<Thread>();
for (int i = 0; i < _threadCount; i++)
{
_threads.Add(new Thread(ThreadProc));
}
_latch = new CountdownLatch();
}
public void Start()
{
foreach (Thread t in _threads)
{
t.Start();
}
}
void ThreadProc()
{
while (true)
{
//Do something
Thread.Sleep(Rand.Next());
_latch.Check();
}
}
internal void Pause()
{
_latch.Increment();
}
internal void Resume()
{
_latch.Decrement();
}
}
public class HighPriorityThreads
{
private Thread _thread;
private LowPriorityThreads _lowPriorityThreads;
internal HighPriorityThreads(LowPriorityThreads lowPriorityThreads)
{
_lowPriorityThreads = lowPriorityThreads;
_thread = new Thread(RandomlyInterruptLowPriortyThreads);
}
public void Start()
{
_thread.Start();
}
void RandomlyInterruptLowPriortyThreads()
{
while (true)
{
Thread.Sleep(Rand.Next());
_lowPriorityThreads.Pause();
Thread.Sleep(Rand.Next());
_lowPriorityThreads.Resume();
}
}
}
class Program
{
static void Main(string[] args)
{
LowPriorityThreads lowPriorityThreads = new LowPriorityThreads(3);
HighPriorityThreads highPriorityThreadOne = new HighPriorityThreads(lowPriorityThreads);
HighPriorityThreads highPriorityThreadTwo = new HighPriorityThreads(lowPriorityThreads);
lowPriorityThreads.Start();
highPriorityThreadOne.Start();
highPriorityThreadTwo.Start();
}
}
class Rand
{
internal static int Next()
{
// Guid idea has been borrowed from somewhere on StackOverFlow coz I like it
return new System.Random(Guid.NewGuid().GetHashCode()).Next() % 30000;
}
}
I don't know about your requirements hence I won't discuss them here.
As far as the implementation goes, I would introduce a "dispatcher" class that will handle inter-threads interaction and also acts a a factory for "runnable" objects.
The implementation, of course is very rough and open for criticism.
class Program
{
static void Main(string[] args)
{
ThreadDispatcher td=new ThreadDispatcher();
Runner r1 = td.CreateHpThread(d=>OnHpThreadRun(d,1));
Runner r2 = td.CreateHpThread(d => OnHpThreadRun(d, 2));
Runner l1 = td.CreateLpThread(d => Console.WriteLine("Running low priority thread 1"));
Runner l2 = td.CreateLpThread(d => Console.WriteLine("Running low priority thread 2"));
Runner l3 = td.CreateLpThread(d => Console.WriteLine("Running low priority thread 3"));
l1.Start();
l2.Start();
l3.Start();
r1.Start();
r2.Start();
Console.ReadLine();
l1.Stop();
l2.Stop();
l3.Stop();
r1.Stop();
r2.Stop();
}
private static void OnHpThreadRun(ThreadDispatcher d,int number)
{
Random r=new Random();
Thread.Sleep(r.Next(100,2000));
d.CheckedIn();
Console.WriteLine(string.Format("*** Starting High Priority Thread {0} ***",number));
Thread.Sleep(r.Next(100, 2000));
Console.WriteLine(string.Format("+++ Finishing High Priority Thread {0} +++", number));
Thread.Sleep(300);
d.CheckedOut();
}
}
public abstract class Runner
{
private Thread _thread;
protected readonly Action<ThreadDispatcher> _action;
private readonly ThreadDispatcher _dispathcer;
private long _running;
readonly ManualResetEvent _stopEvent=new ManualResetEvent(false);
protected Runner(Action<ThreadDispatcher> action,ThreadDispatcher dispathcer)
{
_action = action;
_dispathcer = dispathcer;
}
public void Start()
{
_thread = new Thread(OnThreadStart);
_running = 1;
_thread.Start();
}
public void Stop()
{
_stopEvent.Reset();
Interlocked.Exchange(ref _running, 0);
_stopEvent.WaitOne(2000);
_thread = null;
Console.WriteLine("The thread has been stopped.");
}
protected virtual void OnThreadStart()
{
while (Interlocked.Read(ref _running)!=0)
{
OnStartWork();
_action.Invoke(_dispathcer);
OnFinishWork();
}
OnFinishWork();
_stopEvent.Set();
}
protected abstract void OnStartWork();
protected abstract void OnFinishWork();
}
public class ThreadDispatcher
{
private readonly ManualResetEvent _signal=new ManualResetEvent(true);
private int _hpCheckedInThreads;
private readonly object _lockObject = new object();
public void CheckedIn()
{
lock(_lockObject)
{
_hpCheckedInThreads++;
_signal.Reset();
}
}
public void CheckedOut()
{
lock(_lockObject)
{
if(_hpCheckedInThreads>0)
_hpCheckedInThreads--;
if (_hpCheckedInThreads == 0)
_signal.Set();
}
}
private class HighPriorityThread:Runner
{
public HighPriorityThread(Action<ThreadDispatcher> action, ThreadDispatcher dispatcher) : base(action,dispatcher)
{
}
protected override void OnStartWork()
{
}
protected override void OnFinishWork()
{
}
}
private class LowPriorityRunner:Runner
{
private readonly ThreadDispatcher _dispatcher;
public LowPriorityRunner(Action<ThreadDispatcher> action, ThreadDispatcher dispatcher)
: base(action, dispatcher)
{
_dispatcher = dispatcher;
}
protected override void OnStartWork()
{
Console.WriteLine("LP Thread is waiting for a signal.");
_dispatcher._signal.WaitOne();
Console.WriteLine("LP Thread got the signal.");
}
protected override void OnFinishWork()
{
}
}
public Runner CreateLpThread(Action<ThreadDispatcher> action)
{
return new LowPriorityRunner(action, this);
}
public Runner CreateHpThread(Action<ThreadDispatcher> action)
{
return new HighPriorityThread(action, this);
}
}
}
I have a console app that I want to run continually in the background. I thought that if I started it up and then told it to wait things would work. But when I have it wait, it freezes the application.
Here is my code:
class Program
{
static public ManualResetEvent StopMain;
static void Main(string[] args)
{
// Hide the cursor.
Cursor.Current = Cursors.Default;
StopMain = new ManualResetEvent(false);
RunHook runHook = new RunHook();
// wait until signalled by Program.StopMain.Set();
StopMain.WaitOne();
}
}
class RunHook
{
private HookKeys hook;
public RunHook()
{
hook = new HookKeys();
hook.HookEvent += EventForHook;
}
private void EventForHook(HookEventArgs e, KeyBoardInfo keyBoardInfo,
ref Boolean handled)
{
if ((keyBoardInfo.scanCode == 4) && (keyBoardInfo.vkCode == 114))
handled = true;
}
}
Any ideas on how to have this run in the background but never terminate?
The behavior you see is expected. You have one thread, and it's in a wait state. To get some form of activity, you have to let the scheduler actually do something. A background thread is one way to achieve this:
static void Main(string[] args)
{
StopMain = new ManualResetEvent(false);
bool exit = false;
new Thread(
delegate
{
new RunHook();
while(!exit) { Thread.Sleep(1); }
}
).Start();
StopMain.WaitOne();
exit = true;
}
Another is to just let the primary thread yield:
static void Main(string[] args)
{
StopMain = new ManualResetEvent(false);
RunHook runHook = new RunHook();
while(!StopMain.WaitOne())
{
Thread.Sleep(1);
}
}
There are certainly other ways, too. Personally I'd do neither of these. Instead I'd add a blocking method to the RunHook class and have it return when it was done or signalled.