c# concurrency - Monitor - c#

I have got this code :
if (Monitor.TryEnter(_lock))
{
try
{
ExecuteTask();
}
finally
{
Monitor.Exit(_lock);
}
}
else
{
Monitor.Enter(_lock);
Monitor.Exit(_lock);
}
Basically, if one thread is already executing the task the following threads should just wait for it to finish.
Is there a proper solution as opposed to the one I have found doing :
Monitor.Enter(_lock);
Monitor.Exit(_lock);
Thanks

If there is no need to block the others, you can just use this:
if (Monitor.TryEnter(_lock))
{
try
{
ExecuteTask();
}
finally
{
Monitor.Exit(_lock);
}
}

Personally, I would suggest a solution using Monitor.Wait and Monitor.PulseAll with an additional _executing flag like
Monitor.Enter(_lock);
if (_executing) { // Another thread is running ExecuteTask()
Monitor.Wait(_lock);
Monitor.Exit(_lock);
} else {
_executing = true;
Monitor.Exit(_lock);
try {
ExecuteTask();
} finally {
Monitor.Enter(_lock);
_executing = false;
Monitor.PulsaAll(_lock);
Monitor.Exit(_lock);
}
}
I think this is a bit cleaner: in your solution, holding the lock means "I'm currently updating" as well as "I just waited for another thread to complete the updating". This is not the "original" purpose of a lock (which is to manage exclusive access to some resource).
In my solution, the lock is used to manage exclusive access to the _executing flag.
Also note that the original code might have a subtle bug: I suppose that after one thread has finished ExecuteTask() the next thread arriving at the code should again perform this operation. No imagine this situation:
The first thread reaches the code and starts ExecuteTask()
The next thread reaches the code, TryEnter fails, the thread goes to the else branch and waits for Monitor.Enter() to succeed.
The first thread finishes ExecuteTask() and releases the lock
The second thread Enters the lock in the else branch.
and now:
While the second thread is between Enter and Exit, a third thread reaches the code. TryEnter fails (the second thread holds the lock), the third thread goes to the else branch.
Second thread calls Exit, Third Thread calls Enter, fourth thread arrives, tries Enter, goes to the else branch.
and so on...
So there is a scenario where no further thread ever calls ExecuteTask(), all following threads go straight into the else branch.
In your concrete situation this might be improbable or even impossible, but examples like these usually point to design flaws when it comes to parallel programming.

You can set the time each blocked thread waits using an argument to TryEnter
if (Monitor.TryEnter(_lock,TIMEOUT))//try to acquire lock for TIMEOUT miliseconds
{
try
{
//something
}
finally
{
Monitor.Exit(_lock);
}
}
else//lock was not acquired
{
//Handle TIMEOUT error
}

Related

How can I test if an object is locked, and if not use it within a task about to be called?

I need to do something like the following code. Note, this does not work due to the nature of locks in .Net (which I'll address after the code) but I need some form of implementation like this that works, but I don't know what to do.
static object lockMethod = new object();
static object lockTask = new object();
public static string testLocksAndTasks()
{
//This method is fast executing code but to prevent other issues, I
//lock this method. This might be impertinent to the base need of this
//question, but since I do use a lock on the entire requesting method, I
//put it here. This is because I integrate some logging and a bit of
//other logic on static variables so I just lock the method. This entire
//function is fast. The really slow code is in
//DoWorkInOtherThreadMethod(), which is why it needs to run in a
//background task.
lock (lockMethod)
{
if (Monitor.TryEnter(lockTask))
{
Task.Run(DoWorkInOtherThreadMethod)
.ContinueWith(ct=>
Monitor.Exit(lockTask)); //Oop! Unlocking on separate task NOT ALLOWED!
return "We locked lockTask and started the thread!";
}
else return "Task called and executed by other request!";
}
}
The above code gets the point across for what I'm trying to accomplish. I need to have a method (that is executed from a web request) and I need to test if a launched task from the request is already running in another thread. If it isn't running, I need to create the lock for the task (lockTask in this example) and prevent future calls while it runs, and report ack to the caller the state of the background task. If the lockTask is already in use, I specifically need to return "Task X is already running for Y item". (Note, I didn't include that extra information for what's already running, but that's not difficult to do and not required for this example.)
My code could theoretically work because once the entire task is finished, the call to ContinueWith() would unlock the lock for the task. However, what I've found is that this throws errors because the initial lock on lockTask is created in one thread, and then the subsequent unlock with Monitor.Exit(lockTask) is occurring on another thread and that's not allowed.
I could try to restructure my code to some thing like the code provided below, but this also has issues for my needs.
public static string testLocksAndTasks()
{
lock (lockMethod)
{
//Check if we're locked!
if (!Monitor.IsEntered(lockTask))
{
Task.Run(()=>
{
//We weren't locked, so TryEnter...
if (Monitor.TryEnter(lockTask))
{
DoWorkInOtherThreadMethod();
Monitor.Exit(lockTask); //NOTE: I KNOW THIS SHOULD BE WRAPPED IN A
//TRY/CATCH/FINALLY. I'm just keeping sample
//the code simple.
}
else
{
//Oh no! This is actually quite possible, but this is a case I never
//want to reach?! I can't report this back to the initial call to
//testLocksAndTasks since we are in a new thread!
}
});
return "We locked lockTask and started the thread!";
}
else return "Task called and executed by other request!";
}
}
My comment above outlines the obvious problem. I can create my task lock within the task and this fixes the first issue with the lock and exits happening on separate threads. However, this introduces a different but still important issue.
Since this code can execute semi-simultaneously across multiple request threads, there is a chance that there might be multiple calls to !Monitor.IsEntered(lockTask) returning true because the lock is not set until the Monitor.TryEnter(...) request is made within a new task. This wouldn't be an issue, however, I now can't return a proper state response to testLocksAndTasks().
How can I properly implement something like this where I lock a long running task but can also report if it's running?
Sounds like you don't need a lock but a simple flag indicating whether task is running. Now to read and set this flag you can use regular lock. So you check the flag and start the task if necessary inside the lock. When task is done you again set the flag inside the lock. Sample code:
static object lockTask = new object();
private static bool taskRunning = false;
public static string testLocksAndTasks()
{
lock (lockTask)
{
// check inside the lock
if (!taskRunning)
{
Task.Run(DoWorkInOtherThreadMethod)
.ContinueWith(ct =>
{
lock (lockTask)
{
// reset flag inside the lock
taskRunning = false;
}
});
// start task and set the flag
taskRunning = true;
return "We locked lockTask and started the thread!";
}
else return "Task called and executed by other request!";
}
}

How to find out when a specific thread exits (C#)?

I have a problem here. Is there a way to programmatically find out the moment a certain thread exits? I mean, even the VS debugger gives you that info in its Output window. I know that I simply could make my thread to raise an event but this of course leads to a problem when you spawn more than one thread, so each of them will raise that event, unless you use some toggle variable to make sure that only the first thread to reach that point in code will raise the event.
Here is the beginning of a method that is executed in multiple threads, with cancellation, pause and exit logic shown here. The problem spots of code are the calls to the event handlers (DownloadComplete, DownloadPaused and DownloadCanceled). As you can see, some of them will be executed only once by the first thread that reaches that point and then toggles related bool variables, so other threads won't raise this event again. Another big problem here is the thread exit logic, when the thread doesn't find an item to download and returns with rasing that download complete event which of course will be fired by each thread. Both of these approaches are incorrect and I currently have no any idea how to implement my intended behavior. All I need is to have a clue how to find out a way to catch the momement when the last of the all of spawned thread ends so I could raise all of the mentioned above events just once.
Please note that I have no acess to the types from the System.Threading.Tasks namespace as my project is targeted against .net 2.0. This is my very first experiece with programming something more complex than some class assignment, so I realize that this code is most likely all sorts of terrible.
Sorry for my English.
private void PerformDownload()
{
while (true)
{
if (askedToCancel)
{
lock (lockObj)
{
if (!cancellationPerformed)
{
cancellationPerformed = true;
foreach (DownloadItem di in itemsToProcess)
if (di.Status == DownloadItemStatus.Prepared)
itemsToProcess.UpdateItemStatus(di.URL, DownloadItemStatus.Canceled);
DownloadCanceled();
}
}
return;
}
if (askedToPause)
{
lock (lockObj)
{
if (!pausingPerformed)
{
foreach (DownloadItem di in itemsToProcess)
if (di.Status == DownloadItemStatus.Prepared)
itemsToProcess.UpdateItemStatus(di.URL, DownloadItemStatus.Paused);
DownloadPaused();
}
}
waitHandle.WaitOne();
}
DownloadItem currentItem = null;
lock (lockObj)
{
foreach (DownloadItem di in itemsToProcess)
if (di.Status == DownloadItemStatus.Prepared)
{
currentItem = di;
itemsToProcess.UpdateItemStatus(currentItem.URL, DownloadItemStatus.Downloading);
break;
}
}
if (currentItem == null)
{
DownloadComplete();
return;
}
You can use Interlocked.Increment() and Interlocked.Decrement() on a counter, incrementing at the thread's entry point, decrementing when the thread exits. Then if the counter is non-zero, at least one instance of that thread is running.
For example:
private int _threadCounter;
private void ThreadEntryPoint()
{
try
{
Interlocked.Increment(ref _threadCounter);
// Do thread stuff here
}
finally
{
Interlocked.Decrement(ref _threadCounter);
}
}
That said, it is IMHO not likely to be the best design for it to matter whether the thread is running or not. That is, whenever I think of how that information might be used, it seems to me there's a better way to address the scenario.
Threads exist for a reason, beyond simply being present. So what your code really ought to care about is whether that reason has been addressed, not whether any thread is running. Without a complete code example, I can't really comment on a specific scenario. But I suspect that tracking the actual thread existence is less useful and will be harder to maintain than a more goal-oriented approach.

Thread.Join() causing deadlock

I have three threads in total. The first is the main UI thread, which starts a System.Threading.Thread (ExperimentThread), which in turn starts a BackgroundWorker (WorkerThread).
MainThread and WorkerThread both access a shared resource. I synchronise access to this resource with the following object:
private static readonly Object LockObject = new Object();
which I use as follows in the main loop of each thread:
lock (LockObject)
{
// Do something with shared resource here.
}
A cut-down version of ExperimentThread is as follows:
public void RunExperiment
{
while (!bStopThread)
{
lock (LockObject)
{
// Do something with shared resource here.
}
if (bStopThread)
{
break;
}
else
{
Application.DoEvents();
Thread.Sleep(250);
}
}
}
And for completeness here is the DoWork method of WorkerThread:
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker Worker = sender as BackgroundWorker;
for (int X = 0; X < 200; X++)
{
if (Worker.CancellationPending)
{
e.Cancel = true;
return;
}
lock (LockObject)
{
// Do something with shared resource here.
}
}
}
This seems to work fine when both threads are running freely.
At some point the UI thread will terminate the ExperimentThread by setting one of its boolean fields to true and then wait for it to end, as follows:
if (ExperimentThread.IsAlive)
{
ExperimentThread.StopThread = true;
ExperimentThread.Join(); // this line seems to cause the deadlock?
}
As soon as Join() is called, a deadlock occurs on the shared resource being accessed by ExperimentThread and WorkerThread, and my application hangs indefinitely. This happens maybe 9 out of 10 times.
If I remove ExperimentThread.Join() from the code snippet above, the deadlock never occurs, and ExperimentThread appears to terminate gracefully (it then goes on to terminate WorkerThread by calling CancelAsync()).
Any ideas what could be the problem here?
(P.S. I've been using Console.WriteLine() to determine when locks are taken and released, which is what has lead me to believe there's a deadlock. Is there a better to determine this, I could be wrong?)
Is there a better to determine this, I could be wrong?
A better way to check this is to use something like the Concurrency Visualizer available in higher level SKUs of Visual Studio. It will allow you to see exactly what has locked each thread, and what handles threads are waiting on, etc.
As for the exact reason you are getting a deadlock - there isn't enough code to determine this, but common issues are:
ExperimentThread and the main thread (with the Join() call) are both locking on the same object - ie: within a lock(LockObject) statement.
ExperimentThread is using Control.Invoke to marshal a call back onto the UI thread. Since the UI thread is blocked (waiting on the Join()), it can never process messages, which will prevent ExperimentThread from completing.
That being said, in general, I would recommend using Task or Task<T> instead of a new Thread if you're using .NET 4 or higher. Task provides a much nicer API for working with threads, including allowing continuations instead of blocking. C# 5 extends this to even allow you to asynchronously wait for the task to complete.

Putting the current thread to sleep

I have a unit of work I'm doing in a thread (not the main thread). Under certain circumstances I would like to put this thread to sleep for 10 seconds. Is Thread.Sleep(10000) the most resource efficient way to do this?
Is Thread.Sleep(10000) the most resource efficient way to do this?
Yes in the sense that it is not busy-waiting but giving up the CPU.
But it is wasting a Thread. You shouldn't scale this to many sleeping threads.
As no-one else has mentioned it...
If you want another thread to be able to wake up your "sleeping" thread, you may well want to use Monitor.Wait instead of Thread.Sleep:
private readonly object sharedMonitor;
private bool shouldStop;
public void Stop()
{
lock (sharedMonitor)
{
shouldStop = true;
Monitor.Pulse(sharedMonitor);
}
}
public void Loop()
{
while (true)
{
// Do some work...
lock (sharedMonitor)
{
if (shouldStop)
{
return;
}
Monitor.Wait(sharedMonitor, 10000);
if (shouldStop)
{
return;
}
}
}
}
Note that we only access shouldStop within the lock, so there aren't any memory model concerns.
You may want to loop round waiting until you've really slept for 10 seconds, just in case you get spurious wake-ups - it depends on how important it is that you don't do the work again for another 10 seconds. (I've never knowingly encountered spurious wakes, but I believe they're possible.)
Make a habit of using Thread.CurrentThread.Join(timeout) instead of Thread.Sleep.
The difference is that Join will still do some message pumping (e.g. GUI & COM).
Most of the time it doesn't matter but it makes life easier if you ever need to use some COM or GUI object in your application.
This will process something every x seconds without using a thread
Not sure how not using your own thread compares with a task to run that is created every two seconds
public void LogProcessor()
{
if (_isRunning)
{
WriteNewLogsToDisk();
// Come back in 2 seonds
var t = Task.Run(async delegate
{
await Task.Delay(2000);
LogProcessor();
});
}
}
From resource efficiency, yes.
For design, it depends on the circumstances for the pause. You want your work to be autonomous so if the thread has to pause because it knows to wait then put the pause in the thread code using the static Thread.Sleep method. If the pause happens because of some other external event than you need to control the thread processing, then have the thread owner keep reference to the thread and call childThread.Sleep.
Yes. There's no other efficient or safe way to sleep the thread.
However, if you're doing some work in a loop, you may want to use Sleep in loop to make aborting the thread easier, in case you want to cancel your work.
Here's an example:
bool exit = false;
...
void MyThread()
{
while(!exit)
{
// do your stuff here...
stuff...
// sleep for 10 seconds
int sc = 0;
while(sc < 1000 && !exit) { Thread.Sleep(10); sc++; }
}
}

Compact Framework 2.0: How can I stop a thread when an object is dispose?

I have this code:
Thread t = new Thread(() => UpdateImage(origin));
t.Name = "UpdateImageThread";
t.Start();
This code is created on a Custom Control. I want to stop this thread (if it's running) when the object is going to be dispose.
This custom control has the following method:
void IDisposable.Dispose()
{
/* My own code */
base.Dispose(true);
}
I think this is the place to put the code but:
How can I know is the thread is running?
How can I take a referece for the thread and stop it?
By the way, UpdateImage call a web service, so I think that it's waiting all of its life.
How can I finish this wait?
Thank you!
It depends a lot on what UpdateImage() does and how well it copes with the Image being disposed while it it still active. If UpdateImage() is your code and contains a loop you can tell it to stop (using a field like _stopping). If not, the best thing may be to do nothing - in the rare case of Disposing the control while the image is still updating you take the penalty of leaving it to the GC.
About how to get the Thread: By saving the reference when and where you create it, for instance int the private member _updateThread.
Now actually stopping (aborting) the thread is a (very) bad idea.
So you'll need an indicator, like
private bool _stopping = false;
And it is up to the UpdateImage() method to react to _stopping == true and stop with what it is doing.
Your Dispose() can then use
_stopping = true;
_updateThread.Join()
Save your thread variable 't' so that you can re-use it later.
Within your Dispose method you want something like:
void IDisposable.Dispose()
{
if(t.IsRunning)
{
cancelThreads = true; // Set some cancel signal that the thread should check to determine the end
t.Join(500); // wait for the thread to tidy itself up
t.Abort(); // abort the thread if its not finished
}
base.Dispose(true);
}
You should be careful aborting threads though, ensure that you place critical section of code within regions that won't allow the thread to stop before it has finished, and catch ThreadAbortExceptions to tidy anything up if it is aborted.
You can do something like this in the threads start method
public void DoWork()
{
try
{
while(!cancelThreads)
{
// Do general work
Thread.BeginCriticalRegion();
// Do Important Work
Thread.EndCriticalRegion();
}
}
catch(ThreadAbortException)
{
// Tidy any nastiness that occured killing thread early
}
}
I suggest to override the Dispose method in your Custom Control.
There you have the reference of your thread and you can call .Join() for example...

Categories