How to stop thread when Lock is encountered? - c#

I have the following code that starts some threads:
List<Stuff> lNewStuff = new List<Stuff>();
// populate lNewStuff
for (int i = 0; i < accounts.Length; i++)
{
Account aTemp = _lAccounts.Find(item => item.ID == accounts[i]);
Thread tTemp = new Thread(() => aTemp.ExecuteMe(lNewStuff));
tTemp.Start();
}
Then in the Account class you have the ExecuteMe method that has a lock:
public class Account
{
private Object lockThis = new Object();
public void ExecuteMe(List<Stuff> lNewStuff)
{
//Ensure only one thread at a time can run this code
lock (lockThis)
{
//main code processing
}
}
}
Now, sometimes the thread starts with lNewStuff == null since it sometimes does not find any New Stuff with the Account ID. This is normal for this project. The thread should always try to run but when null I want this thread to die and not wait when a lock is encountered.
So specifically:
If lNewStuff is null and there is a lock then terminate the thread. (how to do this?)
If lNewStuff is null and there is no lock then run normally (does this already)
If lNewStuff is not null and there is a lock then wait for the lock to finish (does this already)
if lNewStuff is not null and there is no lock then run normally (does this already)

When lNewStuff is null you could use Monitor.TryEnter and only continue if the lock is granted:
public class Account
{
private readonly object lockThis = new object();
public void ExecuteMe(List<Stuff> lNewStuff)
{
bool lockTaken = false;
try
{
if (lNewStuff == null)
{
// non-blocking - only takes the lock if it's available
Monitor.TryEnter(lockThis, ref lockTaken);
}
else
{
// blocking - equivalent to the standard lock statement
Monitor.Enter(lockThis, ref lockTaken);
}
if (lockTaken)
{
// main code processing
}
}
finally
{
if (lockTaken)
{
Monitor.Exit(lockThis);
}
}
}
}

If lNewStuff is null and there is a lock then terminate the thread. (how to do this?) ,
do you want to still start a thread if lNewStuff is Null if answer is no then solution must be very simple.
List<Stuff> lNewStuff = new List<Stuff>();
// populate lNewStuff
for (int i = 0; i < accounts.Length; i++)
{
Account aTemp = _lAccounts.Find(item => item.ID == accounts[i]);
if(lNewStuff!=null)
{
Thread tTemp = new Thread(() => aTemp.ExecuteMe(lNewStuff));
tTemp.Start();
}
}
also you shd create a single lock object
private Object lockThis = new Object(); // this statement is creating new lock object with every account object, and hence does not ensure critical section protection.
Change this to
private static Object lockThis = new Object();

Just to be different:
public class Foo : IDisposable
{
private Semaphore _blocker;
public Foo(int maximumAllowed)
{
_blocker = new Semaphore(1,1);
}
public void Dispose()
{
if(_blocker != null)
{
_blocker.Dispose();
_blocker.Close();
}
}
public void LimitedSpaceAvailableActNow(object id)
{
var gotIn = _blocker.WaitOne(0);
if(!gotIn)
{
Console.WriteLine("ID:{0} - No room!", id);
return;
}
Console.WriteLine("ID:{0} - Got in! Taking a nap...", id);
Thread.Sleep(1000);
_blocker.Release();
}
}
Test rig:
void Main()
{
using(var foo = new Foo(1))
{
Enumerable.Range(0, 10)
.Select(t =>
Tuple.Create(t, new Thread(foo.LimitedSpaceAvailableActNow)))
.ToList()
.AsParallel()
.ForAll(t => t.Item2.Start(t.Item1));
Console.ReadLine();
}
}
Output:
ID:4 - Got in! Taking a nap...
ID:8 - No room!
ID:0 - No room!
ID:7 - No room!
ID:2 - No room!
ID:6 - No room!
ID:5 - No room!
ID:9 - No room!
ID:1 - No room!
ID:3 - No room!

Related

C# - How to check if Multi-threading execution has finished? [duplicate]

I have a windows forms app that I am checking all the serial ports to see if a particular device is connected.
This is how I spin off each thread. The below code is already spun off the main gui thread.
foreach (cpsComms.cpsSerial ser in availPorts)
{
Thread t = new Thread(new ParameterizedThreadStart(lookForValidDev));
t.Start((object)ser);//start thread and pass it the port
}
I want the next line of code to wait until all the threads have finished.
I've tried using a t.join in there, but that just processes them linearly.
List<Thread> threads = new List<Thread>();
foreach (cpsComms.cpsSerial ser in availPorts)
{
Thread t = new Thread(new ParameterizedThreadStart(lookForValidDev));
t.Start((object)ser);//start thread and pass it the port
threads.Add(t);
}
foreach(var thread in threads)
{
thread.Join();
}
Edit
I was looking back at this, and I like the following better
availPorts.Select(ser =>
{
Thread thread = new Thread(lookForValidDev);
thread.Start(ser);
return thread;
}).ToList().ForEach(t => t.Join());
Use the AutoResetEvent and ManualResetEvent Classes:
private ManualResetEvent manual = new ManualResetEvent(false);
void Main(string[] args)
{
AutoResetEvent[] autos = new AutoResetEvent[availPorts.Count];
manual.Set();
for (int i = 0; i < availPorts.Count - 1; i++)
{
AutoResetEvent Auto = new AutoResetEvent(false);
autos[i] = Auto;
Thread t = new Thread(() => lookForValidDev(Auto, (object)availPorts[i]));
t.Start();//start thread and pass it the port
}
WaitHandle.WaitAll(autos);
manual.Reset();
}
void lookForValidDev(AutoResetEvent auto, object obj)
{
try
{
manual.WaitOne();
// do something with obj
}
catch (Exception)
{
}
finally
{
auto.Set();
}
}
The simplest and safest way to do this is to use a CountdownEvent. See Albahari.
Store the Thread results in a list after they were spawned and iterate the list - during iteration call join then. You still join linearly, but it should do what you want.
You can use a CountDownLatch:
public class CountDownLatch
{
private int m_remain;
private EventWaitHandle m_event;
public CountDownLatch(int count)
{
Reset(count);
}
public void Reset(int count)
{
if (count < 0)
throw new ArgumentOutOfRangeException();
m_remain = count;
m_event = new ManualResetEvent(false);
if (m_remain == 0)
{
m_event.Set();
}
}
public void Signal()
{
// The last thread to signal also sets the event.
if (Interlocked.Decrement(ref m_remain) == 0)
m_event.Set();
}
public void Wait()
{
m_event.WaitOne();
}
}
Example how to use it:
void StartThreads
{
CountDownLatch latch = new CountDownLatch(availPorts.Count);
foreach (cpsComms.cpsSerial ser in availPorts)
{
Thread t = new Thread(new ParameterizedThreadStart(lookForValidDev));
//start thread and pass it the port and the latch
t.Start((object)new Pair(ser, latch));
}
DoSomeWork();
// wait for all the threads to signal
latch.Wait();
DoSomeMoreWork();
}
// In each thread
void NameOfRunMethod
{
while(running)
{
// do work
}
// Signal that the thread is done running
latch.Signal();
}

Synchronization with semaphore

I try to synchronize three threads (named "1", "2" and "3") using Semaphore class. They have to print a string into console respecting consequence: 1->2->3. Here is my code:
class MyThread
{
public Thread Thrd;
static Semaphore sem = new Semaphore(1, 1);
static int flag = 1;
public MyThread(string name)
{
Thrd = new Thread(this.Run);
Thrd.Name = name;
Thrd.Start();
}
void Run()
{
sem.WaitOne();
if (Convert.ToInt32(Thrd.Name) == flag)
{
Console.WriteLine("Thread " + Thrd.Name);
flag++;
}
if (flag == 4)
flag = 1;
Thread.Sleep(300);
sem.Release();
}
}
class SemaphoreDemo
{
static void Main()
{
for (int i = 0; i < 10; i++)
{
MyThread mt1 = new MyThread("1");
MyThread mt2 = new MyThread("2");
MyThread mt3 = new MyThread("3");
mt1.Thrd.Join();
mt2.Thrd.Join();
mt3.Thrd.Join();
}
}
}
But sometimes strings from threads #2 and #3 are not seen. Where is my mistake and how can I fix this problem?
Thank you very much!
The problem is that sometimes a thread will acquire the semaphore out of order, and you don't have any retry logic. Take a look at your Run method.
void Run()
{
sem.WaitOne();
if (Convert.ToInt32(Thrd.Name) == flag)
{
Console.WriteLine("Thread " + Thrd.Name);
flag++;
}
if (flag == 4)
flag = 1;
Thread.Sleep(300);
sem.Release();
}
Now, what happens if the thread named "3" acquires the semaphore first? flag is equal to 1, so the conditional code won't be executed. The thread will just sleep for 300 milliseconds and then exit. If you want this to work, you have to make the thread retry:
void Run()
{
bool success = false;
while (!success)
{
sem.WaitOne();
if (Convert.ToInt32(Thrd.Name) == flag)
{
Console.WriteLine("Thread " + Thrd.Name);
flag++;
success = true;
}
sem.Release();
if (!success)
{
// let somebody else try
Thread.Sleep(300);
}
}
}
That will make your sample work as expected.
I suspect that this is just an exercise to see how threading and semaphores work. Note, however, that a Mutex is usually more appropriate than a Semaphore with a maximum count of 1.
Note also that there are other ways to make threads execute in sequence, although truthfully if you're going to sequence your threads then you probably don't need more than one thread. Unless those threads are doing other things and they only need to sequence once--or infrequently.

Thread stops running, can't figure out why

In a simple form app I'm running a constant thread when the app starts. Upon its first iteration everything goes smoothly and the thread method "Thread_ContinousChecker" works as intended. After it's run once and the the lockChecker.returnBlock() == true hits then it does not run again. Ie, does not attempt again. I have a hunch that it is something to do with the await lockChecker.checkTime() line but don't understand why, if it works once why would it stop?
Note : It only stops working if the first if statement in the Thread_ContinousChecker method hits, ie if lockChecker.returnBlock() method is true. If it's false, it continues on.
Here is my program class
static class Program
{
//Instantiate the lockform
static LockForm lockForm;
public static bool checkLockForm()
{
Form checker = Application.OpenForms["LockForm"];
return (checker == null);
}
public static void toggleLockForm(bool theBool)
{
//If theBool (our condition) is true start the form
if (theBool == true)
{
//Checks if form already eixsts
if (checkLockForm() == true)
{
//Starts the form
Application.Run(lockForm = new LockForm());
}
}
//Now if theBool is false - we want to close down any instances of the form that we may have started
if (theBool == false)
{
//This is saying if an instance of a LockForm exists
if (checkLockForm() == false)
{
//Rest of app does not close but that lockform is disabled.
//lockForm.Close();
Application.Restart();
}
}
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
MyController cont = new MyController();
//Start new thread for our lock checking
Thread thread = new Thread(new ThreadStart(cont.Thread_ContinuousChecker));
thread.IsBackground = true;
thread.Name = "Data Polling Thread";
thread.Start();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new TrayApp());
}
public class MyController
{
public Boolean checkForm()
{
if (Process.GetProcessesByName("ControlApp.exe").Length > 0)
{
// Is running
return true;
}
if (Process.GetProcessesByName("ControlApp.exe").Length == 0)
{
// Is not running - so start it
return false;
}
return false;
}
public async void Thread_ContinuousChecker()
{
while (true)
{
if (checkForm() == false)
{
LockLogic lockChecker = new LockLogic();
await lockChecker.checkTime();
if (lockChecker.returnBlock() == true)
{
Program.toggleLockForm(true);
}
if (lockChecker.returnBlock() == false)
{
Program.toggleLockForm(false);
}
}
Thread.Sleep(10000);
}
}
}
Here is my LockLogic's .checkTime() method which I'm awaiting in the above Program class
public async Task checkTime()
{
// Read values back from Json file
var serializedList = await Task.Run(() => File.ReadAllText(_filePathTimes));
// getting a list of LockTime objects
var lockTimeList = await Task.Run(() => (List<LockTime>)JsonConvert.DeserializeObject(serializedList, typeof(List<LockTime>), new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Error }));
//
if (lockTimeList == null)
{
return;
}
if(lockTimeList.Count == 0)
{
return;
}
_lockTimes = lockTimeList;
//Then I do a foreach loop to go through every value in the start list and add the same located value to my listOfTimes (the list of LockTime objects with start and end)
for (int x = 0; x < _lockTimes.Count; x++)
{
TimeSpan start = new TimeSpan(_lockTimes[x].Start.Hour, _lockTimes[x].Start.Minute, _lockTimes[x].Start.Second);
TimeSpan end = new TimeSpan(_lockTimes[x].End.Hour, _lockTimes[x].End.Minute, _lockTimes[x].End.Second);
TimeSpan now = new TimeSpan(DateTime.Now.TimeOfDay.Hours, DateTime.Now.TimeOfDay.Minutes, DateTime.Now.TimeOfDay.Seconds);
if ((now > start) && (now < end))
{
_block = true;
}
else
{
_block = false;
}
}
}
A massive thanks to anyone who can spot what's going wrong.
I have a hunch that the problem is your use of Application.Run(lockForm = new LockForm());. As per http://msdn.microsoft.com/en-us/library/ms157902(v=vs.110).aspx, "This method adds an event handler to the mainForm parameter for the Closed event. The event handler calls ExitThread to clean up the application."
So, it's doing what you told it - binding the lifetime of the application to the lifetime of the newly created LockForm.
Hope this helps.

Performant locking pattern

I'm working on the below code and am trying to make it as fast as it can be.
Basically the execute method gets called every time an event gets triggered in the system. What I am testing for is to see whether x number of minutes have passed since a reduce was last performed. If x number of minutes have passed then we should execute the task.
Since the events can be triggered from any thread and happen quite quickly, I thought that triggering the task out side of the lock (even though its a task) would be better than having it in the lock.
Does anyone have any feedback on how this can be improved?
public class TriggerReduce
{
private readonly object _lock = new object();
private readonly int _autoReduceInterval = 5;
private DateTime _lastTriggered;
public void Execute(object sender, EventArgs e)
{
var currentTime = DateTime.Now;
if (currentTime.Subtract(_lastTriggered).Duration().TotalMinutes > _autoReduceInterval)
{
var shouldRun = false;
lock (_lock)
{
if (currentTime.Subtract(_lastTriggered).Duration().TotalMinutes > _autoReduceInterval)
{
_lastTriggered = currentTime;
shouldRun = true;
}
}
if (shouldRun)
{
Task.Factory.StartNew(() =>
{
//Trigger reduce which is a long running task
}, TaskCreationOptions.LongRunning);
}
}
}
}
Oh, I wouldn't do that! Put the 'if (currentTime' and the 'shouldRun' stuff back inside the lock.
Don't change/check state outside a lock - it's sure to screw up.
In this case, a thread that has just set 'shouldRun' to true may have its decision reversed by another thread that enters and sets 'shouldRun' to false again before getting stuck on the lock. The first thread then does not get to the 'StartNew' and the later thread won't either because the first thread set the _lastTriggered to the current time.
OTOH :) since 'shouldRun' is an auto varaible and not a field, it is not state. Only one thread can get inside the lock, double-check the interval and update the _lastTriggered time.
I don't like this kind of double-check but, at the moment, can't see why it would not work.
Would it be helpful to avoid the lock and use Interlocked.Exchange instead?
E.g.
private long _lastTriggeredTicks;
private DateTime lastTriggered
{
get
{
var l = Interlocked.Read( ref _lastTriggeredTicks );
return new DateTime( l );
}
set
{
Interlocked.Exchange( ref _lastTriggeredTicks, value );
}
}
From what I understand Interlocked is faster than a lock statement.
public class TriggerReduce //StartNew is fast and returns fast
{
private readonly object _lock = new object();
private readonly int _triggerIntervalMins = 5;
private DateTime _nextTriggerAt = DateTime.MinValue;
private bool inTrigger = false;
public void Execute(object sender, EventArgs e)
{
lock (_lock)
{
var currentTime = DateTime.Now;
if (_nextTriggerAt > currentTime)
return;
_nextTriggerAt = currentTime.AddMinutes(_triggerIntervalMins);//runs X mins after last task started running (or longer if task took longer than X mins)
}
Task.Factory.StartNew(() =>
{
//Trigger reduce which is a long running task
}, TaskCreationOptions.LongRunning);
}
}
public class TriggerReduce//startNew is a long running function that you want to wait before you recalculate next execution time
{
private readonly object _lock = new object();
private readonly int _triggerIntervalMins = 5;
private DateTime _nextTriggerAt = DateTime.MinValue;
private bool inTrigger = false;
public void Execute(object sender, EventArgs e)
{
var currentTime;
lock (_lock)
{
currentTime = DateTime.Now;
if (inTrigger || (_nextTriggerAt > currentTime))
return;
inTrigger = true;
}
Task.Factory.StartNew(() =>
{
//Trigger reduce which is a long running task
}, TaskCreationOptions.LongRunning);
lock (_lock)
{
inTrigger = false;
_nextTriggerAt = DateTime.Now.AddMinutes(_triggerIntervalMins);//runs X mins after task finishes
//_nextTriggerAt = currentTime.AddMinutes(_triggerIntervalMins);//runs X mins after last task started running (or longer if task took longer than X mins)
}
}
}
Use Monitor.TryEnter.
if (Monitor.TryEnter(_lock))
{
try
{
if (currentTime.Subtract(_lastTriggered).Duration().TotalMinutes >
_autoReduceInterval)
{
_lastTriggered = currentTime;
shouldRun = true;
}
}
finally
{
Monitor.Exit(_lock);
}
}
I think you already have a fairly reasonable approach. The big problem is that you are accessing _lastTriggered outside of the lock. The double-checked locking idiom is not going to work here. Simply your code so that it looks like this.
public void Execute(object sender, EventArgs e)
{
var currentTime = DateTime.Now;
var shouldRun = false;
lock (_lock)
{
TimeSpan span = currentTime - _lastTriggeed;
if (span.TotalMinutes > _autoReduceInterval)
{
_lastTriggered = currentTime;
shouldRun = true;
}
}
if (shouldRun)
{
Task.Factory.StartNew(() =>
{
//Trigger reduce which is a long running task
}, TaskCreationOptions.LongRunning);
}
}

Executing method by timer inside threadpool

In my multi threaded web app I invoke in the ThreadPool SomeMethod which can throw an exception. Suppose I want to make a few attempts if it causes an exception at first call. I decide to use System.Timers.Timer inside my action for attempts. Can I use the code below? Is it safely?
static void Caller()
{
ThreadPool.QueueUserWorkItem(action =>
{
try
{
SomeMethod();
Console.WriteLine("Done.");
}
catch
{
var t = new System.Timers.Timer(1000);
t.Start();
var count = 0;
t.Elapsed += new System.Timers.ElapsedEventHandler((o, a) =>
{
var timer = o as System.Timers.Timer;
count++;
var done = false;
Exception exception = null;
try
{
Console.WriteLine(count);
SomeMethod();
done = true;
}
catch (Exception ex)
{
exception = ex;
}
if (done || count == 10)
{
Console.WriteLine(String.Format("Stopped. done: {0}, count: {1}", done, count));
t.Stop();
if (!done) throw exception;
}
});
}
});
Thread.Sleep(100000);
}
static void SomeMethod()
{
var x = 1 / new Random().Next(0, 2);
}
You should Dispose each Timer after use, that's for sure. But, probably you could do something even simpler:
static void Main()
{
ThreadPool.QueueUserWorkItem(action =>
{
while (TrySomeMethod() == false)
Thread.Sleep(1000);
});
// wait here
Console.Read();
}
static bool TrySomeMethod()
{
try
{
SomeMethod();
return true;
}
catch
{
return false;
}
}
I do not think that using a timer in a thread pool thread is a safe approach. I may be wrong, but the timer will raise its elapsed event when the thread method has already been finished to execute. In this case, the exception will be thrown. Also, I do not see that you are not disposing the timer which leads to resource leaks. If you explain why you need the timer, I will try to find a safe solution...
I don't see the point of using a Timer within a ThreadPool queue, because the ThreadPool would spawn a new thread, and the Timer would spawn a new thread as well.
I would just have a loop within that delegate, because it would not block the main thread either way. Groo showed a good example of that.

Categories

Resources