I'm very new to threading, so I'm not sure if I'm doing this right, but would appreciate some assistance. I have the following code to run when the user clicks the mouse; it basically runs some path-finding code and moves the player.
However, my problem is when I click the mouse again while the thread is running, it causes issues. Is there a way to stop the previous thread and start a new one when this code is reached a second time?
private void checkMouse()
{
mouseCommand mc = new mouseCommand();
Thread oThread = new Thread(() => mc.leftClick(Mouse.GetState().X,Mouse.GetState().Y));
oThread.Start();
}
Perhaps something like this would work for you?
private object lock_object - new object();
private Thread oThread = new Thread();
private void checkMouse()
{
lock(lock_object)
{
if (oThread.ThreadState != ThreadState.Running)
{
mouseCommand mc = new mouseCommand();
oThread = new Thread(() => mc.leftClick(Mouse.GetState().X,Mouse.GetState().Y));
oThread.Start();
}
}
}
There's a few ways you can do this.
The simplest, and the first you should learn about when learning about threading is a lock. Have an object that you use to lock on this and any related actions that would also cause problem if they happened together:
private object lockObj = new object();
private static void DoLClick()
{
lock(lockObj)
{
mouseCommand mc = new mouseCommand();
mc.leftClick(Mouse.GetState().X,Mouse.GetState().Y));
}
}
private void checkMouse()
{
Thread oThread = new Thread(DoLClick);
oThread.Start();
}
The benefit is that this keeps threads from stepping on each other toes.
The downside is the loss of concurrency (all these threads are waiting on each other, instead of doing something) and the risk of deadlock (if thread A has lock 1 and needs lock 2 and thread B has lock 2 and needs lock 1, you're stuck).
It remains the simplest approach. Often even if you're going to need to use another approach, it's well worth starting with some widely defined locks, and then changing to narrower locks (that is, locks that cover less code) or different approaches later.
Another possibility is to have a lock, but instead of using lock(){} to obtain it, you use Monitor.TryEnter() with a time-out (perhaps of zero) and just give up if you don't get it:
private object lockObj = new object();
private static void DoLClick()
{
if(!Monitor.TryEnter(lockObj, 0))
return; // Just do nothing if we're busy.
try
{
mouseCommand mc = new mouseCommand();
mc.leftClick(Mouse.GetState().X,Mouse.GetState().Y));
}
finally
{
Monitor.Exit(lockObj);
}
}
private void checkMouse()
{
Thread oThread = new Thread(DoLClick);
oThread.Start();
}
The downside is that you don't get that second task done. The upside is that you often don't want something done if it's already being done, and you get that for free.
Some other approaches are a variant of this, where you've a thread-safe object describing tasks to do; it could be an integer count of actions that need doing that you use Interlocked.Increment() and Interlocked.Decrement() to change, or a ConcurrentQueue of objects that describe the task that needs doing. Then you could have the thread that failed to get the lock add to that, and that which did get the lock take over that thread's work when it's finished. Or you could perhaps have a dedicated thread that just keeps looking for work to do, and waits on an AutoResetEvent whenever it runs out of work - threads giving it work (adding to the queue) set that event to make sure it's not just sitting doing nothing.
All these possibilities (and more) are worth learning about, and have their place, but the first suggestion with lock is the first to learn.
Related
I have some code that I have been going over to learn the system and I ran across some code that to me is a code smell and I wouldn't think it would work at all, but it does.
We have two objects, object A and object B. Object A contains a lock object:
private object lockObj = new object();
Object B will grab a lock on object A.lockObj and while B has the lock it calls
A.SomeMethod();
A.SomeMethod() acquires a lock on
this.lockObj
And to show it in code:
ThreadTestOne:
public class ThreadTestOne
{
public object lockObject = new object();
private List<string> lst;
private ThreadTestTwo two;
public List<string> Lst
{
get
{
return this.lst;
}
set
{
this.lst = value;
}
}
public void Run()
{
lst = new List<string>();
two = new ThreadTestTwo();
two.Run(this);
}
public void End()
{
Console.WriteLine("ThreadTestOne.End");
two.End();
}
public void LockMe()
{
Console.WriteLine("ThreadTestOne.LockMe");
lock (this.lockObject)
lst.Add("something");
Thread.Sleep(500);
}
}
ThreadTestTwo:
public class ThreadTestTwo
{
private ThreadTestOne one;
private Thread myThread;
private bool ending = false;
public void Run(ThreadTestOne a)
{
one = a;
myThread = new Thread(new ThreadStart(Consume));
Console.WriteLine("ThreadTestTwo Starting thread");
myThread.Start();
}
public void End()
{
Console.WriteLine("ThreadTestTwo.End");
ending = true;
myThread.Join();
}
public void Consume()
{
while (!ending)
{
Console.WriteLine("ThreadTestTwo one.lockObject");
lock (one.lockObject)
{
Console.WriteLine("two.LockMe");
one.LockMe();
one.Lst.Add("two");
Thread.Sleep(500);
}
}
}
}
When I look over the above code, I think it should break as one.LockMe() should never be able to acquire a lock on lockObj because it ThreadTestTwo already has the lock.
I thought this would result in a deadlock. However, when I run the above example code, it works. Also, the code I was reviewing also works and is currently in production.
The fact that this doesn't result in an exception being thrown is confusing to me. Am I incorrect in assuming this should be an error?
In the code that I was testing originally only reading data after trying to acquire the lock twice so I had thought that the compiler was removing the lock.
However, I looked in the MSIL and saw that the lock is still there.
My next thought was the framework just wasn't acquiring the lock because we are just reading data.
I add a write operation within the lock and it still worked. However, it is possible that I don't fully understand how locking work.
Even though this works, I feel that it is wrong and I am not fully convinced that this will not cause issues in production.
I did find this question:
use the same lock object at two different code block?
Which is similar but I believe my issue is slightly different, I'm asking about locking an object when the calling method has already has a lock on that same object.
Obviously the code I have a question about works and I would like to know how?
Am I incorrect in assuming this is wrong?
There are a couple of issues that I am aware of in the above code.
public field - I know this is wrong, but that is how it is in the code.
Circular reference - I'm aware of the circular reference and know why it is bad.
Thank you for any insight you can provide.
You seem to be under the impression that a class owns a lock (aka monitor). That's not the case - a thread owns a monitor.
Monitors in .NET are re-entrant - if a thread already has the monitor, it can acquire it again. That will increase the "lock count" for it - when the thread releases the monitor the first time, it will just decrease the lock count, but as the count will still be positive, no other thread will be able to acquire the monitor until the original thread has released it again.
From Monitor.Enter (the method that the lock keyword sort-of calls - it actually calls TryEnter, but...):
It is legal for the same thread to invoke Enter more than once without it blocking; however, an equal number of Exit calls must be invoked before other threads waiting on the object will unblock.
I'm trying to simulate (very basic & simple) OS process manager subsystem, I have three "processes" (workers) writing something to console (this is an example):
public class Message
{
public Message() { }
public void Show()
{
while (true)
{
Console.WriteLine("Something");
Thread.Sleep(100);
}
}
}
Each worker is supposed to be run on a different thread. That's how I do it now:
I have a Process class which constructor takes Action delegate and starts a thread from it and suspends it.
public class Process
{
Thread thrd;
Action act;
public Process(Action act)
{
this.act = act;
thrd = new Thread(new ThreadStart(this.act));
thrd.Start();
thrd.Suspend();
}
public void Suspend()
{
thrd.Suspend();
}
public void Resume()
{
thrd.Resume();
}
}
In that state it waits before my scheduler resumes it, gives it a time slice to run, then suspends it again.
public void Scheduler()
{
while (true)
{
//ProcessQueue is just FIFO queue for processes
//MainQueue is FIFO queue for ProcessQueue's
ProcessQueue currentQueue = mainQueue.Dequeue();
int count = currentQueue.Count;
if (currentQueue.Count > 0)
{
while (count > 0)
{
Process currentProcess = currentQueue.GetNext();
currentProcess.Resume();
//this is the time slice given to the process
Thread.Sleep(1000);
currentProcess.Suspend();
Console.WriteLine();
currentQueue.Add(currentProcess);
count--;
}
}
mainQueue.Enqueue(currentQueue);
}
}
The problem is that it doesn't work consistently. It even doesn't work at all in this state, i have to add Thread.Sleep() before WriteLine in Show() method of the worker, like this.
public void Show()
{
while (true)
{
Thread.Sleep(100); //Without this line code doesn't work
Console.WriteLine("Something");
Thread.Sleep(100);
}
}
I've been trying to use ManualResetEvent instead of suspend/resume, it works, but since that event is shared, all threads relying on it wake up simultaneously, while I need only one specific thread to be active at one time.
If some could help me figure out how to pause/resume task/thread normally, that'd be great.
What I'm doing is trying to simulate simple preemptive multitasking.
Thanks.
Thread.Suspend is evil. It is about as evil as Thread.Abort. Almost no code is safe in the presence of being paused at arbitrary, unpredictable locations. It might hold a lock that causes other threads to pause as well. You quickly run into deadlocks or unpredictable stalls in other parts of the system.
Imagine you were accidentally pausing the static constructor of string. Now all code that wants to use a string is halted as well. Regex internally uses a locked cache. If you pause while this lock is taken all Regex related code might pause. These are just two egregious examples.
Probably, suspending some code deep inside the Console class is having unintended consequences.
I'm not sure what to recommend to you. This seems to be an academic exercise so thankfully this is not a production problem for you. User-mode waiting and cancellation must be cooperative in practice.
I manage to solve this problem using static class with array of ManualResetEvent's, where each process is identified by it's unique ID. But I think it's pretty dirty way to do it. I'm open to other ways of accomplishing this.
UPD: added locks to guarantee thread safety
public sealed class ControlEvent
{
private static ManualResetEvent[] control = new ManualResetEvent[100];
private static readonly object _locker = new object();
private ControlEvent() { }
public static object Locker
{
get
{
return _locker;
}
}
public static void Set(int PID)
{
control[PID].Set();
}
public static void Reset(int PID)
{
control[PID].Reset();
}
public static ManualResetEvent Init(int PID)
{
control[PID] = new ManualResetEvent(false);
return control[PID];
}
}
In worker class
public class RandomNumber
{
static Random R = new Random();
ManualResetEvent evt;
public ManualResetEvent Event
{
get
{
return evt;
}
set
{
evt = value;
}
}
public void Show()
{
while (true)
{
evt.WaitOne();
lock (ControlEvent.Locker)
{
Console.WriteLine("Random number: " + R.Next(1000));
}
Thread.Sleep(100);
}
}
}
At Process creation event
RandomNumber R = new RandomNumber();
Process proc = new Process(new Action(R.Show));
R.Event = ControlEvent.Init(proc.PID);
And, finally, in scheduler
public void Scheduler()
{
while (true)
{
ProcessQueue currentQueue = mainQueue.Dequeue();
int count = currentQueue.Count;
if (currentQueue.Count > 0)
{
while (count > 0)
{
Process currentProcess = currentQueue.GetNext();
//this wakes the thread
ControlEvent.Set(currentProcess.PID);
Thread.Sleep(quant);
//this makes it wait again
ControlEvent.Reset(currentProcess.PID);
currentQueue.Add(currentProcess);
count--;
}
}
mainQueue.Enqueue(currentQueue);
}
}
The single best advice I can give with regard to Suspend() and Resume(): Don't use it. You are doing it wrong™.
Whenever you feel a temptation to use Suspend() and Resume() pairs to control your threads, you should step back immediately and ask yourself, what you are doing here. I understand, that programmers tend to think of the execution of code paths as of something that must be controlled, like some dumb zombie worker that needs permament command and control. That's probably a function of the stuff learned about computers in school and university: Computers do only what you tell them.
Ladies & Gentlemen, here's the bad news: If you are doing it that way, this is called "micro management", and some even would call it "control freak thinking".
Instead, I would strongly encorage you to think about it in a different way. Try to think of your threads as intelligent entities, that do no harm and the only thing they want is to be fed with enough work. They just need a little guidance, that's all. You may place a container full of work just in front of them (work task queue) and have them pulling the tasks from that container themselves, as soon as the finished their previous task. When the container is empty, all tasks are processed and there's nothing left to do, they are allowed to fall asleep and WaitFor(alarm) which will be signaled whenever new tasks arrive.
So instead of command-and-controlling a herd of dumb zombie slaves that can't do anything right without you cracking the whip behind them, you deliberately guide a team of intelligent co-workers and just let it happen. That's the way a scalable architecture is built. You don't have to be a control freak, just have a little faith in your own code.
Of course, as always, there are exceptions to that rule. But there aren't that many, and I would recommend to start with the work hypothesis, that your code is probably the rule, rather than the exception.
Imagine this code:
public class Kitchen(){
private readonly Mutex kitchenLock = new Mutex(true, "Kitchen");
private readonly object _lock = new Object();
public void Enter(){
lock(_lock){
kitchenLock.WaitOne(-1); //wait indefinitely
}
}
public void DoCooking(){
//cook stuff...
}
public void Leave(){
lock(_lock){
kitchenLock.ReleaseMutex();
}
}
}
On my function bellow, called by a zillion of different and bad behaved threads i do this:
Kitchen kit = new Kitchen();
kit.Enter();
kit.DoCooking();
kit.Leave();
Everything is fine in the code above. But the kit.Leave() throws a AbandonMutexException, why is that? Can find an answer... I muted the exception and it works fine. Is it a safe guard of .NET?
It is a very serious threading bug, you cannot ignore it. Your code is calling Enter() but not Leave(). Which gets you a mutex that is acquired but will never be released, a guaranteed recipe for deadlock.
Luckily, .NET can detect the mishap, the thread that owns the mutex stopped running which automatically means it is never going to call ReleaseMutex(). That's always bad, so it raises the exception to help you realize that your code has a deadlock bug. At the very minimum, you need a hard guarantee that ReleaseMutex() is always called, even if there's an exception:
Kitchen kit = new Kitchen();
kit.Enter();
try {
kit.DoCooking();
}
finally {
kit.Leave();
}
Albeit that the code looks too fake to be actually usable as-is.
Thanks everyone that tried to answer my question, but I've found the answer myself.
Besides the comments regarding bugs, there is no bug in this code :) (sorry), instead there is a misunderstand of the meaning of initiallyOwned parameter when instantiating the kitchen mutex.
Mutex MSDN documentation can be found here and says:
Initializes a new instance of the Mutex class with a Boolean value that indicates whether the
calling thread should have initial ownership of the mutex, and a string that is the name of the
mutex.
But at the beginning that didn't make much sense, so I thought yes the creating thread should own the mutex, why not? don't even know what this means, but sound good!
Although after seeing all MSDN examples regarding this I understood what it means to be initiallyOwned, initiallyOwned means that the thread that creates mutex has an implicit call to the mutex WaitOne method, meaning, obviously, that the thread Initially OWNS IT!
Here is an MSDN example:
// Create a new Mutex. The creating thread owns the
// Mutex.
private static Mutex mut = new Mutex(true);
private const int numIterations = 1;
private const int numThreads = 3;
static void Main()
{
// Create the threads that will use the protected resource.
for(int i = 0; i < numThreads; i++)
{
Thread myThread = new Thread(new ThreadStart(MyThreadProc));
myThread.Name = String.Format("Thread{0}", i + 1);
myThread.Start();
}
// Wait one second before allowing other threads to
// acquire the Mutex.
Console.WriteLine("Creating thread owns the Mutex.");
Thread.Sleep(1000);
Console.WriteLine("Creating thread releases the Mutex.\r\n");
mut.ReleaseMutex();
}
private static void MyThreadProc()
{
for(int i = 0; i < numIterations; i++)
{
UseResource();
}
}
// This method represents a resource that must be synchronized
// so that only one thread at a time can enter.
private static void UseResource()
{
// Wait until it is safe to enter.
mut.WaitOne();
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name);
// Place code to access non-reentrant resources here.
// Simulate some work.
Thread.Sleep(500);
Console.WriteLine("{0} is leaving the protected area\r\n",
Thread.CurrentThread.Name);
// Release the Mutex.
mut.ReleaseMutex();
}
So as you can see Main does not call mut.WaitOne(-1) if it had called it like I DO in my example it means that the thread running main would have to call ReleaseMutex 2 times instead of just one.
You can be wondering, what?! But how can the thread call 2 times WaitOne, are you mad, actually this is very interesting, because since the thread calling Main initially owns the Mutex, it would have to ReleaseMutex also 2 times, as specified here:
If a thread owns a Mutex, that thread can specify the same Mutex in repeated wait-request calls
without blocking its execution; however, it must release the Mutex as many times to release
ownership.
And that's it,
Regards.
So I'm seeing fun stuff playing with threads.
I have a method that starts 2 threads and goes on with its life and I tried doing the following to keep things safe.
bool CopyOk1 = false;
bool CopyOk2 = false;
new Thread(() => FirstMethod(tempList1, ref CopyOk1)).Start();
new Thread(() => SecondMethod(tempList2, ref CopyOk2)).Start();
var spinner = new SpinWait();
while (!CopyOk1 || !CopyOk2)
spinner.SpinOnce();
then in both methods I start with the following
private static void FirstMethod(List<T> templist, ref bool CopyOk)
{
var temp = new T[templist.Count];
templist.CopyTo(temp);
CopyOk = true;
//moves on
}
My intention here is to copy the passed list so I can change and use it safely inside the threads ASAP to unblock the caller thread.
My problem is that on the second method unpredictably, between the array initialization and the list CopyTo the base list changes, somehow, by something.
These lists are created inside the caller thread and are not actually used after the threads are started so I have absolutely NO idea how/why this is happening.
No doubt I'm doing something wrong here, but my noobish skills won't let me see, any help is appreciated.
Instead of locking 'templist', use a global lock. Then protect all code that modifies the source list with that same lock.
Also, perhaps an aside, but waiting for a thread to partially complete can be done more elegantly, i.e not involving a loop. Using a ManualResetEvent will allow your original thread to wait for 'something' to occur in other threads. Using WaitOne will block the thread until a Set() is called in the other thread.
private object m_Lock = new object();
private ManualResetEvent m_ResetOne = new ManualResetEvent(false);
private ManualResetEvent m_ResetTwo = new ManualResetEvent(false);
(...)
new Thread(() => FirstMethod(tempList1)).Start();
new Thread(() => SecondMethod(tempList2)).Start();
m_ResetOne.WaitOne();
m_ResetTwo.WaitOne();
(...)
private void FirstMethod(List<T> templist)
{
lock (m_Lock)
{
var temp = new T[templist.Count];
templist.CopyTo(temp);
}
m_ResetOne .Set();
//moves on
}
Nothing in the code that you posted suggests that you are doing anything wrong. The problem has to lie elsewhere- most likely, as commenters have suggested, in the code that populates List1/List2. If you are threading that as well, perhaps you are not waiting for that thread to finish populating the lists before proceeding?
Try this and check the behavior
private static void FirstMethod(List<T> templist, ref bool CopyOk)
{
T[] temp;
lock (templist)
{
temp = new T[templist.Count];
templist.CopyTo(temp);
}
CopyOk = true;
//moves on
}
You need some type of synchronization mechanism to prevent List<T> from being changed. We can't see enough code in the current sample to warrant that it is not being altered.
Monitor moni = new Monitor();
Thread t = new Thread(() => moni.CurrUsage(nics,200));
t.Start();
I start a thread named 't' inside the 'Form1_Load' function. I have added a button. When click on that button the thread 't' should stop executing and create a new thread with these parameters.
Monitor moni = new Monitor();
Thread t = new Thread(() => moni.CurrUsage(nics,950));
t.Start();
I know in the form_load event i can use the
t.Abort();
By making t a member of the form, you can reference it later on in the button-click event handler.
Graceful Abort.
Although t.Abort() gets the job done, you might be left with half-processed data in the thread t. You can catch the ThreadAbortException in thread t to gracefully end processing.
Beware of overlap.
The second problem is that your thread might not have aborted yet while your new thread has started already. You can prevent that by calling t.Join() after calling t.Abort().
Hope this helps.
Make Thread t a private member of your form.
public partial class MainForm : Form
{
private Thread t;
}
One way is to make Thread t a global variable (place outside of Form_Load). Then it can be accessed and modified from any method in that class.
To instantiate the thread, use t = new Thread(.....
Before aborting the thread, make sure it is not null.
You need to make the Thread object accessable in both places that you need to access it.
In this case, making it a private varaible would work.
e.g.
public class MyClass
{
private Thread MyThread
{
get;
set;
}
private void myfunc1()
{
MyThread = new Thread(() => moni.CurrUsage(nics,200));
MyThread.Start();
}
private void myfunc2()
{
MyThread.Abort();
// I really need to wait until this thread has stopped...
MyThread.Join();
}
}
Adding to the already given answers:
Note that .Join() will block your current (UI) thread, leaving your application unresponsive to the user.
Just as another take: avoid using .Abort() by using a flag in your Monitor class to exit the task you are doing if possible. You can then still wait for .Join(), but you have full control of the state in the background thread.
public class Monitor
{
private bool _cancel = false;
public void Cancel()
{
_cancel = true;
}
public void CurrUsage(Nics nics, int n)
{
_cancel = false;
// ...
while (!_cancel)
{
// do some stuff
}
}
}
in your Form
private Monitor _monitor { get; set; }
private Thread _t;
public void Button_Click(...)
{
_monitor.Cancel()
_t.Join() // will return as your background thread has finished cleanly
_t = new Thread(() => _monitor.CurrUsage(nics,950));
t.Start();
}
As others have pointed out, all you need in order to call Abort is a reference to the thread (just like any other object in .NET).
However
You should seriously consider rethinking this approach. In general, calling Abort is discouraged, as it does not give the target thread sufficient opportunity to reach a stopping point. While it's sometimes appropriate (or the only option), it's almost always a better idea to ask the target thread to stop (usually through a volatile bool rather than forcing it like this.
For example,
public class ThreadClass
{
private volatile bool stopRequested;
private Thread thread;
public void Start()
{
stopRequested = false;
thread = new Thread(ThreadMethod);
thread.Start();
}
public void Stop()
{
stopRequested = true;
if(!thread.Join(5000)) thread.Abort(); // forcefully abort if not
// completed within 5 seconds
}
private void ThreadMethod()
{
}
}
Your code then goes into ThreadMethod. Within the method, periodically check the value of stopRequested. If it's true, perform whatever cleanup is necessary (if any) and gracefully return out of the thread. If the content is a loop, the general practice is to place the check at the start of the loop (assuming that the loop is sufficiently tight) and exit early if the value is true. The exact placement is really dependent upon the code, but the general idea is that it should be checked often enough to make the thread exit fairly quickly after it gets set, regardless of when that happens.