How to make sure threaded task is run - c#

Not really language specific, but I have this in C#:
public static void StartJob() {
ThreadPool.QueueUserWorkItem(s => {
if (Monitor.TryEnter(_lock)) {
ProcessRows();
Monitor.Exit(_lock);
}
}
);
ProcessRows() processes and removes rows in a database until all rows are removed. At program launch and whenever a row is added to the database elsewhere in the program, StartJob is called, to ensure all rows are processed without blocking the program. Now if a row is added at exactly the same time as StartJob is about to release the lock, it will not be processed.
How do I ensure that all rows are processed? I prefer not to have ProcessRows() run unless rows are added.

Don't lock around the method; lock within the method using a flag that says whether you're running or not.
One implementation might look like the code below - in this case I've moved all the logic into ProcessRows and made the method return immediately if it's already running.
public static bool _isRunning = false;
public static void StartJob()
{
ThreadPool.QueueUserWorkItem(s => { ProcessRows(); })
}
public static void ProcessRows()
{
Monitor.Enter(_lock);
if (_isRunning)
{
Monitor.Exit(_lock);
return;
}
_isRunning = true;
while (rowsToProcess)
{
Monitor.Exit(_lock);;
// ... do your stuff
Monitor.Enter(_lock);
}
_isRunning = false;
Monitor.Exit(_lock);
}
With this structure, it's impossible for the while loop to complete without setting _isRunning = false - if this weren't the case, there would be a race condition if the loop completed just as another instance of the method started. Equally, when the method is called, it will always enter the loop and set _isRunning = true before another instance gets a chance to execute.

Related

Is the `is` operator thread-safe/atomic in C#?

Is the following code thread-safe?
public object DemoObject {get;set;}
public void DemoMethod()
{
if (DemoObject is IDemoInterface demo)
{
demo.DoSomething();
}
}
If other threads modify DemoObject (e.g. set to null) while DemoMethod is being processed, is it guaranteed that within the if block the local variable demo will always be assigned correctly (to an instance of type IDemoInterface)?
The is construct here is atomic much like interlocked. However the behavior of this code is almost 100% non deterministic. Unless the objective is to create unpredictable and non deterministic behavior this would be a bug.
Valid usage example of this code: In a game to simulate the possibility of some non deterministic event such as "Neo from the Matrix catching a bullet in mid air", this method may be more non deterministic that simply using a pseudo random number generator.
In any scenario where deterministic / predictable behavior is expected this code is a bug.
Explanation:
if (DemoObject is IDemoInterface demo)
is evaluated and assigned pseudo atomically.
Thereafter within the if statement:
even if DemoObject is set to null by another thread the value of demo has already been assigned and the DoSomething() operation is executed on the already assigned instance.
To answer your comment questions:
why is there a race?
The race condition is by design in this code. In the example code below:
16 threads are competing to set the value of DemoObject to null
while another 16 threads are competing to set the value of DemoObject to an instance of DemoClass.
At the same time 16 threads are competing to execute DoSomething() whenever they win the race condition when DemoObject is NOT null.
See: What is a race condition?
and why can i not predict whether DoSomething() will execute?
DoSomething() will execute each time
if (DemoObject is IDemoInterface demo)
evaluates to true. Each time DemoObject is null or NOT IDemoInterface it will NOT execute.
You cannot predict when it will execute. You can only predict that it will execute whenever the thread executing DoSomething() manages to get a reference to a non null instance of DemoObject. Or in other words when a thread running DemoMethod() manages to win the race condition:
A) after a thread running DemoMethod_Assign() wins the race condition
B) and before a thread running DemoMethod_Null() wins the race condition
Caveat: As per my understanding (Someone else please clarify this point) DemoObject may be both null and not null at the same time across different threads.
DemoObject may be read from cache or may be read from main memory. We cannot make it volatile since it is an object reference. Therefore the state of DemoObject may be simultaneously Null for one thread and not null for another thread. Meaning its value is non deterministic. In Schrödinger's cat, the cat is both dead and alive simultaneously. We have much the same situation here.
There are no locks or memory barriers in this code with respect to DemoObject. However a thread context switch forces the equivalent of a memory barrier. Therefore any thread resuming after a context switch will have an accurate copy of the value of DemoObject as retrieved from main memory. However a different thread may have altered the value of DemoObject but this altered value may not have been flushed to main memory yet. Which then brings into question which is the actual accurate value? The value fetched from main memory or the value not yet flushed to main memory.
Note: Someone else please clarify this Caveat as I may have missed something.
Here is some code to validate everything above except the Caveat. Ran this console app test on a machine with 64 logical cores. Null reference exception is never thrown.
internal class Program
{
private static ManualResetEvent BenchWaitHandle = new ManualResetEvent(false);
private class DemoClass : IDemoInterface
{
public void DoSomething()
{
Interlocked.Increment(ref Program.DidSomethingCount);
}
}
private interface IDemoInterface
{
void DoSomething();
}
private static object DemoObject { get; set; }
public static volatile int DidSomethingCount = 0;
private static void DemoMethod()
{
BenchWaitHandle.WaitOne();
for (int i = 0; i < 100000000; i++)
{
try
{
if (DemoObject is IDemoInterface demo)
{
demo.DoSomething();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
private static bool m_IsRunning = false;
private static object RunningLock = new object();
private static bool IsRunning
{
get { lock (RunningLock) { return m_IsRunning; } }
set { lock(RunningLock) { m_IsRunning = value; } }
}
private static void DemoMethod_Assign()
{
BenchWaitHandle.WaitOne();
while (IsRunning)
{
DemoObject = new DemoClass();
}
}
private static void DemoMethod_Null()
{
BenchWaitHandle.WaitOne();
while (IsRunning)
{
DemoObject = null;
}
}
static void Main(string[] args)
{
List<Thread> threadsListDoWork = new List<Thread>();
List<Thread> threadsList = new List<Thread>();
BenchWaitHandle.Reset();
for (int I =0; I < 16; I++)
{
threadsListDoWork.Add(new Thread(new ThreadStart(DemoMethod)));
threadsList.Add(new Thread(new ThreadStart(DemoMethod_Assign)));
threadsList.Add(new Thread(new ThreadStart(DemoMethod_Null)));
}
foreach (Thread t in threadsListDoWork)
{
t.Start();
}
foreach (Thread t in threadsList)
{
t.Start();
}
IsRunning = true;
BenchWaitHandle.Set();
foreach (Thread t in threadsListDoWork)
{
t.Join();
}
IsRunning = false;
foreach (Thread t in threadsList)
{
t.Join();
}
Console.WriteLine(#"Did Something {0} times", DidSomethingCount);
Console.ReadLine();
}
//On the last run this printed
//Did Something 112780926 times
//Which means that DemoMethod() threads won the race condition slightly over 7% of the time.

Thread-safe replace for code?

In process of developing I often face with the next problem: if some method is already executed by one thread - method is must not be executed by another thread. Another thread must do nothing - simple exit from method, beacuse of it I can't use "lock". Usually, I solve this problem like that:
private bool _isSomeMethodExecuted = false;
public void SomeMethod ()
{
if (!this._isSomeMethodExecuted) //check if method is already executed
{
this._isSomeMethodExecuted = true;
//Main code of method
this._isSomeMethodExecuted = false;
}
}
But this code is not thread-safe: if one thread execute condition statement but It be stopped before set flag in true and another thread can execute condition - then both threads are inside method code.
Is there any thread-safe replace for it?
the following is thread-safe and does not block if the method is already executing - even if it is alreasy executing on the same thread... which provides protection from reentrancy for all scenarios.
private long _isSomeMethodExecuted = 0;
public void SomeMethod ()
{
if (Interlocked.Increment (ref this._isSomeMethodExecuted) == 1) //check if method is already executed
{
//Main code of method
}
Interlocked.Decrement (ref this._isSomeMethodExecuted);
}
For refrences see http://msdn.microsoft.com/en-us/library/zs86dyzy.aspx
Monitor does this job for you, but the lock is thread-wide (and therefore open for recursive calls!). The lock statement uses a Monitor too (using the blocking Enter method), but you may work with the TryEnter method instead:
if(Monitor.TryEnter(myLockObject))
{
try
{
DoSomething(); // main code
}
finally
{
Monitor.Exit(myLockObject);
}
}
TryEnter does not block but returns a bool indicating whether the lock was successfully acquired or not.
If you want recursive calls not to enter the main code block again, you should use a semaphore instead. Semaphores use counters instead of locking objects, so you cannot reenter even from the same thread:
class Program
{
private static Semaphore sem = new Semaphore(1, 1);
static void Main(string[] args)
{
MyMethod();
MyMethod();
}
private static void MyMethod()
{
if(sem.WaitOne(0))
{
try
{
Console.WriteLine("Entered.");
MyMethod(); // recursive calls won't re-enter
}
finally
{
sem.Release();
}
}
else
{
Console.WriteLine("Not entered.");
}
}
}

I wonder is there a better way to implement this "simple lock"

Is there a better way to do implement a simple lock like below?
I only want to to the "DOSOMETHING" if it's not already being run. Should I be using reall locks here? if I use lock will that cause everything to queue up and wait for the lock to release? (that's not what I want!)
Thanks
bool running = false;
void DataDisplayView_Paint(object sender, PaintEventArgs e)
{
// if (!this.initialSetDone)
if (!running)
{
this.running = true;
//DOSOMETHING
this.running = false;
}
}
No, you do not want to use locks here. This is not a thread synchronization problem. This is a method reentrancy problem.
You might try something like this.
bool running = false;
void DataDisplayView_Paint(object sender, PaintEventArgs e)
{
if (!this.running)
{
this.running = true;
try
{
//DOSOMETHING
}
finally
{
this.running = false;
}
}
}
You just need to synchronise (lock is the simplest way) bits of the code:
bool running = false;
readonly object padlock = new object();
void DataDisplayView_Paint(object sender, PaintEventArgs e)
{
if (!this.initialSetDone)
{
lock(padlock)
{
if(running) return;
running = true;
}
try {
//DOSOMETHING
}
finally
{
lock(padlock)
{
this.running = false;
}
}
}
}
The best way is to use a try/finally block
try {
this.running = true;
...
} finally {
this.running = false;
}
Real thread locks are only needed if this method is called from multiple threads. Given that it appears to be a paint event handler this is unlikely as controls are affinitized to a single thread.
Am I missing something? The code as you've posted it does not seem to do anything. That is, the code will run whether or not running is true.
Generally, any code that tries to "lock" itself like this...
if (!running)
{
running = true;
try
{
// This code should not call itself recursively.
// However, it may execute simultaneously on more than one thread
// in very rare cases.
}
finally
{
running = false;
}
}
...is perfectly good, as long as you're in a single-threaded scenario. If you're running multi-threaded code, problems can arise because you are assuming that no two threads will reach the if (!running) line at the same time.
The solution in multi-threaded code is to use some form of atomic switch. I've used the AutoResetEvent for this purpose:
var ready = new AutoResetEvent(true);
if (ready.WaitOne(0))
{
try
{
// This code will never be running on more than one thread
// at a time.
}
finally
{
ready.Set();
}
}
Note that if you're having reentrancy on your paint callback, you've got a more serious problem. Paint handlers should be blocking your message pump (and should complete relatively quickly), so you should never see this case. The only exception is if you call Application.DoEvents() from somewhere in your paint handler, which you really shouldn't be doing.
You shift varaible names in the middle, so I'm going to assume you wanted:
bool running = false;
void DataDisplayView_Paint(object sender, PaintEventArgs e)
{
if (!this.running)
{
this.running = true;
//DOSOMETHING
this.running = false;
}
}
The problem you have here is that if DataDisplayView_Paint can be called from multiple threads, then it is possible that between the if (!this.running) and the this.running = true; the other thread could jump in and start DOSOMETHING (because running is still false). Then the first thread will resume, and start DOSOMETHING again. If that is a possiblity, then you will need to use a real lock.
If you use Monitor.TryEnter instead you could specify a timeout, in which case the result you get is such that:
only one thread can run the DOSOMETHING at a time
subsequent calls will try to get the lock and give up after the timeout clause
If you don't provide with a timeout, or set the timeout to 0, this call won't block and will return immediately (maybe that'd suit your requirement better?):
if (!this.initialSetDone && Monitor.TryEnter(_lock))
{
// DOSOMETHING
}
Alternatively, you can make the running variable volatile so that you will always get the latest value stored in the variable:
private volatile bool running;
if (!this.initialSetDone && !this.running) // #1
{
this.running = true;
try
{
// DOSOMETHING
}
finally
{
this.running = false;
}
}
The second approach won't queue up subsequent calls, but there is the possibility that two threads will both hit #1 and evaluate that it's safe to proceed then both end up running DOSOMETHING, though it's highly unlikely.
I only want to to the "DOSOMETHING" if
it's not already being run
Your question doesn't have enough information, so I can't help but make assumptions about your code.
My first assumption is that, based on the signature DataDisplayView_Paint(object s, PaintEventArgs e), your code runs on the GUI thread.
My second assumption is that your code DOSOMETHING is synchronous.
With that in mind, here's version of your code which guarantees we only run DOSOMETHING if its not already being run:
void DataDisplayView_Paint(object s, PaintEventArgs e)
{
//DOSOMETHING
}
The GUI thread will only process one message at a time, and your DataDisplayView_Paint method does not exit until DOSOMETHING completes. If you're doing anything with the GUI like drawing to a Graphics object or changing labels, then this code won't get invoked from more than one thread -- and if it does, .NET will throw an exception. In other words, you don't need any synchronization.
Let's assume DOSOMETHING runs asyncronously -- now we have an interesting problem, but its very easy to solve, and you don't need any bools.
Essentially, all you're doing is disabling your event handler while DOSOMETHING runs, then re-enabling it. Instead of using a bool, unhook and rehook your event handler as needed:
void DataDisplayView_Paint(object s, PaintEventArgs e)
{
DataDisplayView.Paint -= DataDisplayView_Paint;
DoSomethingAsynchronously(); // re-hooks event handler when completed
}
void DoSomethingAsychronously()
{
ThreadPool.QueueUserWorkItem(() =>
{
try
{
// DOSOMETHING
}
finally
{
// may need a lock around this statement
DataDisplayView.Paint += DataDisplayView_Paint;
}
});
}

Explain the code: c# locking feature and threads

I used this pattern in a few projects, (this snipped of code is from CodeCampServer), I understand what it does, but I'm really interesting in an explanation about this pattern. Specifically:
Why is the double check of _dependenciesRegistered.
Why to use lock (Lock){}.
Thanks.
public class DependencyRegistrarModule : IHttpModule
{
private static bool _dependenciesRegistered;
private static readonly object Lock = new object();
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
}
public void Dispose() { }
private static void context_BeginRequest(object sender, EventArgs e)
{
EnsureDependenciesRegistered();
}
private static void EnsureDependenciesRegistered()
{
if (!_dependenciesRegistered)
{
lock (Lock)
{
if (!_dependenciesRegistered)
{
new DependencyRegistrar().ConfigureOnStartup();
_dependenciesRegistered = true;
}
}
}
}
}
This is the Double-checked locking pattern.
The lock statement ensures that the code inside the block will not run on two threads simultaneously.
Since a lock statement is somewhat expensive, the code checks whether it's already been initialized before entering the lock.
However, because a different thread might have initialized it just after the outer check, it needs to check again inside the lock.
Note that this is not the best way to do it.
The double-check is because two threads could hit EnsureDependenciesRegistered at the same time, both find it isn't registered, and thus both attempt to get the lock.
lock(Lock) is essentially a form of mutex; only one thread can have the lock - the other must wait until the lock is released (at the end of the lock(...) {...} statement).
So in this scenario, a thread might (although unlikely) have been the second thread into the lock - so each must double-check in case it was the second, and the work has already been done.
It's a matter of performance.
The initial test lets it bail out quickly if the job is already done. At this point it does the potentially expensive lock but it has to check it again as another thread could have already registered it.
The double checked locking pattern is roughly:
you have an operation that you want to conditionally perform once
if (needsToDoSomething) {
DoSomething();
needsToDoSomething = false;
}
however, if you're running on two threads, both threads might check the flag, and perform the action, before they both set the flag to false. Therefore, you add a lock.
lock (Lock) {
if (needsToDoSomething) {
DoSomething();
needsToDoSomething = false;
}
}
however, taking a lock every time you run this code might be slow, so you decide, lets only try to take the lock when we actually need to.
if (needsToDoSomething)
lock (Lock) {
if (needsToDoSomething) {
DoSomething();
needsToDoSomething = false;
}
}
You can't remove the inner check, because once again, you have the problem that any check performed outside of a lock can possibly turn out to be true twice on two different threads.
The lock prevents two threads from running ConfigureOnStartup(). Between the if (!_dependenciesRegistered) and the point that ConfigureOnStartup() sets _dependenciesRegistered = true, another thread could check if it's registered. In other words:
Thread 1: _dependenciesRegistered == false
Thread 2: _dependenciesRegistered == false
Thread 1: ConfigureOnStartup() / _dependenciesRegistered = true;
Thread 2: Doesn't "see" that it's already registered, so runs ConfigureOnStartup() again.

Please help me make this code thread safe

I've got a bit of a problem with making my data loading and filtering thread safe.
The following code on my control's base class which handles all the data population through a BackgroundWorker. This tends to throw the error on "this.DataWorker.RunWorkerAsync()" saying that the BackgroundWorker is busy.
/// <summary>
/// Handles the population of the form data.
/// </summary>
/// <param name="reload">Whether to pull data back from the WebService.</param>
public void Populate(bool reload)
{
if (!this.DataWorker.IsBusy)
{
// Disable the filter options
IvdSession.Instance.FilterManager.SetEnabledState(this.GetType(), false);
// Perform the population
this.DataWorker.RunWorkerAsync(reload);
}
else if (!reload)
{
// If the data worker is busy and this is a not reload, then something bad has happened (i.e. the filter has run during a reload.)
throw new InvalidOperationException("The DataWorker was busy whilst asked to reload.");
}
}
The code is called in two possible places. Firstly by a timer on the form that the control is on:
private void tmrAutoRefresh_Tick(object sender, EventArgs e)
{
if (!(this.CurrentBody == null))
{
this.CurrentBody.Populate(true);
}
}
And secondly, any time a user selects a Filter Option from a number of drop down lists:
public void Filter()
{
if (!m_BlockFilter)
{
IvdInstance.Main.CurrentBody.FirstRun = true;
IvdInstance.Main.CurrentBody.Populate(false);
}
}
The Timer on the main form runs every 60 seconds and passes true to the Populate method. Passing reload as trues tells the BackgroundWorker that it needs to pull down a fresh set of data from the WebService:
void dataWorker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
if (base.FirstRun)
{
base.CleanListView();
}
if ((bool)e.Argument)
{
byte[] serialized = IvdSession.DataAccess.GetServiceCalls(IvdSession.Instance.Company.Description, IvdSession.Instance.Company.Password, null);
m_DataCollection = new DalCollection<ServiceCallEntity>(serialized);
}
List<ServiceCallEntity> collection = this.ApplyFilter();
base.HandlePopulation<ServiceCallEntity>(collection, e);
}
catch (WebException ex)
{
// Ignore - Thrown when user clicks cancel
}
catch (System.Web.Services.Protocols.SoapException ex)
{
// Log error on server and stay transparent to user
base.LogError(ex);
}
catch (System.Data.SqlClient.SqlException ex)
{
// Inform user that the database is unavailable
base.HandleSystemUnavailable(ex);
}
}
As far as I'm aware, the error occurs when I manage to click a filter option at exactly the same time the Timer fires the population event. I figure there is something missing from the Populate method, i.e. a lock, but I'm unsure as to how to use it correctly in this instance.
The code is favoured towards the user input. If a user selects a filter option, the auto update should be blocked, if the auto update fires then the filter options are temporarily disabled. If they fire at the same time, the user input should get priority (if possible).
Hope someone can help!
First, add a lock around your Populate method body:
private object _exclusiveAccessLock = new object();
public void Populate(bool reload)
{
lock (_exclusiveAccessLock)
{
// start the job
}
}
This will help you avoid a race condition (although: if I got it right, since you are using a Windows.Forms Timer, it will always fire from the Gui thread, so they should never be executed exactly at the same time).
Next, I am not sure if you should throw the exception at all. You can, for example, set an additional flag that shows you that the worker hasn't finished yet, but that is what IsBusy should tell you anyway.
Then there is the m_BlockFilter flag. I cannot see where you are setting it from. It should be set inside the lock also, not in the background thread, because in that case you cannot be sure that it will not be delayed. You also need to make the field volatile if you are going to use it as a cross-thread flag.
See Thread Synchronization (C# Programming Guide):
public class TestThreading
{
private System.Object lockThis = new System.Object();
public void Function()
{
lock (lockThis)
{
// Access thread-sensitive resources.
}
}
}
Edit: You don't want two threads entering Populate, so you could do something as bellow:
public void Populate(bool reload)
{
lock (lockThis)
{
// Disable the filter options
IvdSession.Instance.FilterManager.SetEnabledState(this.GetType(), false);
// do actual work.
}
}
Edit2: You got good thing going with BackgroundWorker, so maybe you could do something like this to let the other thread wait.
public void Populate(bool reload)
{
while (this.DataWorker.IsBusy) {
Thread.Sleep(100);
}
// Disable the filter options
IvdSession.Instance.FilterManager.SetEnabledState(this.GetType(), false);
// Perform the population
this.DataWorker.RunWorkerAsync(reload);
}

Categories

Resources