c# Thread syncronization problem - c#

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.

Related

WaitHandle fundamental behavior

Have those two code blocks the same effect when looking at the console?
Please note: Currently I am still using and bound to .NET 3.5.
First:
for(int i = 0; i<3;i++)
{
Console.WriteLine(i);
}
Second:
class Worker
{
static int i = 0;
static ManualResetEvent manualResetEvent = new ManualResetEvent(false);
static Object locky = new Object();
static void Work(Object workItem)
{
WaitHandle[] wait = new [] { manualResetEvent };
while (WaitHandle.WaitAny(wait))
{
lock (locky)
{
Console.WriteLine(i++);
}
}
}
}
// main:
Thread thread = new Thread(Worker.Work);
thread.Start();
for (int i=0;i<3;i++)
{
Worker.manualResetEvent.Set();
}
Will the waitHandle increase with every signal? Will the loop run until all signals are done?
Or will a signal be ignored when the thread is already working?
Can someone please bring some light into this?
Since you're using a ManualResetEvent, once you signal the event, it remains signaled until it's reset. Which means setting it once or three times will have the same effect.
This also means that the worker will go into an infinite loop because the event is never reset.
Also, you can't lock on value types. If you could, the int would be boxed and create a new object every time you lock on it - which means you'd be locking on a different object every single time, rendering the lock useless.

C# Threading Query

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.

How to abort a thread started inside another function?

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.

Questions about multi-threading

If I have a that thread:
Thread sendMessage = new Thread(new ThreadStart(timer.Start()));
will, the Tick event of the timer will be on the main thread or on the sendMessage thread?
Edit:
I have a queue and i want that every x milisecond the timer will tick and the program will dequeue arrays from the queue, but this is my code:
Thread sendMessage = new Thread(new ThreadStart(startThreadTimer));
public Queue<Array> messageQueue = new Queue<Array>();
System.Threading.Timer timer;
private void startThreadTimer()
{
System.Threading.TimerCallback cb = new System.Threading.TimerCallback(checkIfQueue);
timer = new System.Threading.Timer(cb, null, 4000, 30);
}
private static void checkIfQueue(object obj)
{
}
and I can't call a none static method or use a none static field from the checkIfQueue, and it have to be static, what can i do?
Edit:
Here is the code that one of you sent me, I cahnged him so it fitts to my goal, will it work?
public ConcurrentQueue<Array> messageQueue = new ConcurrentQueue<Array>();
public void Example()
{
var thread = new Thread(
() =>
{
while (true)
{
Array array;
byte[] byteArray = {};
if (messageQueue.Count > 0)
{
messageQueue.TryDequeue(out array);
foreach (byte result in array)
{
byteArray[byteArray.Length] = result;
}
controllernp.Write(byteArray, 0, 100);
}
Thread.Sleep(30);
}
});
thread.IsBackground = true;
thread.Start();
}
It depends on the type of timer. Most timers (System.Timers.Timer or System.Threading.Timer) that can work in a background thread use a ThreadPool thread for their Tick event. In this case, the answer is "neither" thread.
If your timer is a Windows Forms timer or a DispatcherTimer, it will likely cause an exception, since they need to be run on the UI thread, and can't be run on a background thread.
This is going to depend on exactly which timer you are using. The .NET Framework has several timers;
System.Threading.Timer = Could be on any available thread.
System.Windows.Forms.Timer = Should be on the "UI" thread.
System.Timer.Timer = Could be on any available thread.
And probably more that I'm missing.
As mentioned, there are two timers; System.Threading.Timer and System.Windows.Forms.Timer. The first kind may execute on any thread, except the thread you started it from (unless it's part of the threadpool, and your function has returned, then it might be executed there, eventually.)
The second kind, the Windows Forms kind, may execute on either your thread, or another thread. It depends.
The timer needs a window handle, and depending on which thread the handle is created, the Tick event will fire on different threads. The internal window the timer uses is created when it's needed for the first time. Most likely, you have created the timer on the main (GUI) thread, but that will not create the actual window inside the timer. To ensure that the window is created on the main thread you will have to first start, and then stop, the timer at least one time. (It's when started for the first time the window is created.)
(If you didn't get it: the timer uses an internal window to receive the tick event. The window is created on a thread, and that thread needs to have message loop running. The thread that is first to start the timer will create the window, and receive the Tick event. Hopefully that thread is running a messageloop.)
If you are wanting to dequeue items from a queue every X milliseconds then why use a timer at all? It is much easier to spawn a new thread that spins around an infinite loop.
public class Example
{
private ConcurrentQueue<Array> m_Queue = new ConcurrentQueue<Array>();
public Example(int intervalMilliseconds)
{
var thread = new Thread(
() =>
{
while (true)
{
Array array;
while (m_Queue.TryDequeue(out array))
{
// Process the array here.
}
Thread.Sleep(intervalMilliseconds);
}
});
thread.IsBackground = true;
thread.Start();
}
public void Enqueue(Array array)
{
m_Queue.Enqueue(array);
}
}
Update:
No, your method is not thread-safe. The problem is with how you are dequeueing items.
if (messageQueue.Count > 0)
{
messageQueue.TryDequeue(out array);
}
It should really look like this.
if (messageQueue.TryDequeue(out array)
{
}
The TryDequeue method returns false if the queue is empty so it already does the check and dequeue in one atomic operation.

How to Cancel a Thread?

In case of BackgroundWorker, a cancel can be reported by the e.Cancel - property of the DoWork - event handler.
How can I achieve the same thing with a Thread object?
Here is a full example of one way of doing it.
private static bool _runThread;
private static object _runThreadLock = new object();
private static void Main(string[] args)
{
_runThread = true;
Thread t = new Thread(() =>
{
Console.WriteLine("Starting thread...");
bool _localRunThread = true;
while (_localRunThread)
{
Console.WriteLine("Working...");
Thread.Sleep(1000);
lock (_runThreadLock)
{
_localRunThread = _runThread;
}
}
Console.WriteLine("Exiting thread...");
});
t.Start();
// wait for any key press, and then exit the app
Console.ReadKey();
// tell the thread to stop
lock (_runThreadLock)
{
_runThread = false;
}
// wait for the thread to finish
t.Join();
Console.WriteLine("All done.");
}
In short; the thread checks a bool flag, and keeps runing as long as the flag is true. I prefer this approach over calling Thread.Abort becuase it seems a bit nicer and cleaner.
Generally you do it by the thread's execute being a delegate to a method on an object, with that object exposing a Cancel property, and the long-running operation periodically chercking that property for tru to determine whether to exit.
for example
public class MyLongTunningTask
{
public MyLongRunninTask() {}
public volatile bool Cancel {get; set; }
public void ExecuteLongRunningTask()
{
while(!this.Cancel)
{
// Do something long running.
// you may still like to check Cancel periodically and exit gracefully if its true
}
}
}
Then elsewhere:
var longRunning = new MyLongTunningTask();
Thread myThread = new Thread(new ThreadStart(longRunning.ExecuteLongRunningTask));
myThread.Start();
// somewhere else
longRunning.Cancel = true;
A blocked thread can be stopped prematurely in one of two ways:
Thread.Interrupt
Thread.Abort
The main question is if the thread works on any ressources which need to be released correctly - in this case - you need to work with a property on the actual object which runs the thread.
There's Thread.Abort, which works by injecting a ThreadAbortException into the thread. It's a little risky because:
Your thread can get stuck if it's executing native code at the time
The code in the thread better be exception-safe, because this ThreadAbortException could happen on any line of code within it, even something innocent like i = i + 1
You're better off coding your own signalling mechanism between your GUI thread and the background thread. It's hard to recommend something without knowing what's going on inside that thread, but where I have a thread that works by waiting on some object in a loop, I use an AutoResetEvent and wait on that too.

Categories

Resources