ReaderWriterLockSlim EnterReadLock() over several methods, one running in a BackgroundWorker - c#

In my application I use a ReaderWriterLockSlim to synchronize reads and writes from/to a list<>.
In the following example reading the list is performed inside all 3 sub-methods, thus these 3 should be packed into a ReadLock. The problem is that SubMethod3 is called via a BackgroundWorker (as it contains lengthy calculations), so the ExitReadLock() in the finally block of MainMethod1 might be called before SubMethod3 has been finished by the BackgroundWorker (separate thread). Thereby the code in SubMethod3 is not really protected by the lock.
What I have considered is to use a lock in each sub-method, so Submethod3 would have its own lock, which would be released when the BackgroundWorker was done. The problem with this approach is that another thread could enter in between the calls of the sub-methods, as each of these would release the lock when done.
My question is: How can ReadLock be used to protect over more threads?
ReaderWriterLockSlim synchronizationLock = new ReaderWriterLockSlim();
public void MainMethod1()
{
synchronizationLock.EnterReadLock();
try
{
SubMethod1(); //Run on UI thread
SubMethod2(); //Run on UI thread
myBackgroundWorker.RunWorkerAsync();
}
finally
{
synchronizationLock.ExitReadLock();
}
}
private void myBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
SubMethod3(); //Run on separate thread
}

In general you are out of luck. Due to thread affinity, you cannot release the lock from another thread. If you try to hold the reader lock (with the idea that this will allow the worker to acquire its own read lock), and wait the worker thread to start, acquire a reader lock and notify you, so you can release the read lock at that time, all you'll get would be a deadlock if there is a waiting writer thread due to reader/waiter fairness of the ReaderWriterLock(Slim) implementation.
I see the following options:
(A) Run the whole MainMethod1 on a separate thread.
(B) Write and use your own reader/writer lock implementation that supports such scenario.
(C) Get rid of BackgroundWorker and switch to async/await implementation using one of the AsyncReaderWriterLock implementations described here ReaderWriterLockSlim and async\await
(D) Since I've noticed the comment Run on UI thread, only and only if the method is used by a thread that supports marshalling calls from another thread (which is true for WF and WPF UI threads), you can use the following technique:
public void MainMethod1()
{
synchronizationLock.EnterReadLock();
bool releaseLock = true;
try
{
SubMethod1();
SubMethod2();
RunWorkerCompletedEventHandler onRunWorkerCompleted = null;
onRunWorkerCompleted = (sender, e) =>
{
((BackgroundWorker)sender).RunWorkerCompleted -= onRunWorkerCompleted;
synchronizationLock.ExitReadLock();
};
myBackgroundWorker.RunWorkerCompleted += onRunWorkerCompleted;
myBackgroundWorker.RunWorkerAsync();
releaseLock = false;
}
finally
{
if (releaseLock)
synchronizationLock.ExitReadLock();
}
}
Please note than while option (D) seems to solve the issue in the context of MainMethod1, it can easily lead to a deadlock if the UI thread tries to acquire read lock from another place and there is a pending writer waiting.
In general working with long time hold locks from the UI thread is a bad idea that is causing more problems rather than solving something. IMO the best are the options (A) and (C), and so far (A) is the simplest if you can afford it (if SubMethod1 and SubMethod2 do not need to be run on the UI thread or can marshall the necessary calls to it).

Related

Thread and Task scheduling

I have a code which synchronize threads via AutoResetEvent
Basically there are two threads which swap control and execute commands , each thread at a time.
Code :
static EventWaitHandle _waitHandle = new AutoResetEvent(false);
static void Waiter()
{
_waitHandle.WaitOne();
Console.WriteLine("A...");
_waitHandle.Set();
_waitHandle.WaitOne();
Console.WriteLine("A2...");
_waitHandle.Set();
}
static void Waiter2()
{
_waitHandle.WaitOne();
Console.WriteLine("B...");
_waitHandle.Set();
_waitHandle.WaitOne();
Console.WriteLine("B2...");
}
void Main()
{
new Thread(Waiter).Start();
new Thread(Waiter2).Start();
_waitHandle.Set(); // Wake up the Waiter.
}
Result : (I always get this result)
A...
B...
A2...
B2...
However - when I move to Tasks :
Task.Run(()=>Waiter());
Task.Run(()=>Waiter2());
I sometimes get :
B...
A...
B2...
Which is clear to me because the task scheduler scheduled the second task to execute first.
Which leads me to ask :
Questions
1) Do threads order guaranteed to be the same as order of invocation in :
new Thread(Waiter).Start();
new Thread(Waiter2).Start();
//In other words , will I always get the first result ?
2) How can I Force the Task.Runs to be invoked the same order as I invoke them?
No, it is not guaranteed, you just got lucky that the output was the same every time.
Add in a 2nd AutoResetEvent that has a WaitOne between the two tasks and a Set in at the start of the Waiter method.
Without a synchronization mechanism, you cannot guarantee the order in which a thread will start and/or execute. Furthermore, a thread's execution may be preempted (think: "paused") at any time.
So to answer your questions:
No
No
Before moving forward, you should ask yourself "Do I really need to use threads to solve this problem?"
My favorite quote from the Microsoft's MSDN:
"When you use multithreading of any sort, you potentially expose yourself to very serious and complex bugs" [Best Practices for Implementing the Event-based Asynchronous Pattern]
If you do need to introduce threads, then I would begin by familiarizing yourself with some of Microsoft's synchronization mechanisms:
Critical Section
Mutex
Events
Auto Reset
Manual Reset

c# synchronisation How lock behaves

I have question regarding threading in c#.See the code posted below.
public class TestThreading
{
private System.Object lockThis = new System.Object();
public void Function1()
{
lock (lockThis)
{
// Access thread-sensitive resources.
}
}
public void Function2(){
lock (lockThis)
{
// Access thread-sensitive resources.
}
}
}
Now my question is if some thread entered in Function1 (inside lock block) and at the same time another thread enters in Function2 what will happen
The threads will execute independently.
The thread which entered in Function 2 Goes to waits until lock is released by Funtion1 thread.
The thread which entered in Function 2 throws exception.
I am new to c# hence asking simple basic question.
Thanks in advance.
The thread which entered in Function 2 Goes to waits until lock is released by Funtion1 thread.
The purpose of the lock is just that: provide a "safe" region of code that can be accessed only by one thread at a time. The other thread will be put to sleep, and resumed when the first one releases the lock.
Number 2 will happen. The second thread will wait for the lock to be released before executing.
The second thread will wait for the first one to release the lock and only then it will acquire the lock and preform your code
I suggest reading the following articles which describe MultiThreading issues and libraries
Managed Threading Best Practices
Threading in C#
Joseph Albahari

stopping my thread

I have a thread that I am trying to discontinue. What I have done is the following.
randomImages = new Thread(new ThreadStart(this.chooseRandomImage));
randomImages.Start();
This is the method called by the thread
bool threadAlive = true;
public void chooseRandomImage()
{
while(threadAlive)
{
try
{
//do stuff
}
catch (Exception exe)
{
MessageBox.Show(exe.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
Now, upon clicking a stop thread button I simply set threadAlive to false.
Problem is the thread doesnt stop immediately, as if it has gathered a form of momentum.
How can a stop a thread instantly, and possibly restart it again?
private void butStopThread_Click(object sender, EventArgs e)
{
threadAlive = false;
if(threadAlive == false)
{
//do stuff
}
}
I am sorry, that IS the best way to do it. Using .NET 4.0 upward you should use tasks, not threads, and then there is this thing called CancellationToken that pretty much does the same as your variable.
Then, after cancelling, you wait until the processing is finishing. If that needs to happen fast, then - well - make the check for the cancellation more granular, i.e. check more often.
Aborting threads has possibly significant side effects as explained at http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation - this is why the method generally should not be used.
And no, stopped threads etc. can not be restarted magically - this you have to put into your logic (restart points, save points ,long running transaction in steps, remembering where it finished).
As a sidenote - if you insist on not using tasks and have access to the latest versin of .NET, Volatile is not needed if you use the Interlocked access class methods, which ago down to some assembler instructions that are thread safe per definition.
It is possible to terminate a thread from another thread with a call
to Abort, but this forcefully terminates the affected thread without
concern for whether it has completed its task and provides no
opportunity for the cleanup of resources. The technique shown in this
example is preferred.
You need to use Abort method BUT IS NOT RECOMMENDED
From the information provided by you, it seems the threadAlive variable is being accessed by both the worker thread and the UI thread. Try declaring threadAlive using volatile keyword which is ensure cross-thread access happens without synchronization issues.
volatile bool threadAlive;
To restart the thread, you first need to ensure that it performs all necessary cleanup. Use the Join method call on your thread object in the main/UI thread to make sure your thread terminates safely. To restart, simply invoke the Start method on the thread.
randomImages.Join();

C# non-UI cross-thread invocation

I'm trying to make cross-threaded calls in C#.
Whenever I invoke the methods of an object created in the context of thread A from a static method called from thread B, the method always runs in thread B. I don't want that, I want it run on the same thread as the thread A object whose methods I am calling.
Invoke works fine for UI calls and I've read dozens of articles and SO answers relating to different ways of making cross-threaded Forms/WPF calls. However whatever I try (event handling, delegates, etc) Thread A's object's method will always run in Thread B if it is invoked by Thread B.
What part of the library should I be looking in to solve this? If it's relevant, Thread B currently 'spins', reads from a network port and occasionally invokes Thread A's object's method through a delegate that was created in Thread A and passed in using a ParameterizedThreadStart.
I'm not looking to change paradigm, just send a message (a request to invoke a method) from one thread (Thread B) to another (Thread A).
EDIT:
My question was 'what part of the library should I be looking in to solve this?' The answer appears to be none. If I want to clearly delineate consumption and polling I'll have to write my own code to handle that.
Whenever I invoke the methods of an object running on thread A
Objects don't run on threads.
In order for this to work, you will have to create some kind of queue you can shove a delegate into that will be routinely checked thread A's main loop. Something like this, assuming that Something.MainThreadLoop is the entry point for thread A:
public class Something
{
private Queue<Action> actionQueue = new Queue<Action>();
private volatile bool threadRunning = true;
public void RunOnThread(Action action)
{
if (action == null)
throw new ArgumentNullException("action");
lock (actionQueue)
actionQueue.Enqueue(action);
}
public void Stop()
{
threadRunning = false;
}
private void RunPendingActions()
{
while (actionQueue.Count > 0) {
Action action;
lock (actionQueue)
action = actionQueue.Dequeue();
action();
}
}
public void MainThreadLoop()
{
while (threadRunning) {
// Do the stuff you were already doing on this thread.
// Then, periodically...
RunPendingActions();
}
}
}
Then, given a reference to a Something object, you could do this:
something.RunOnThread(() => Console.WriteLine("I was printed from thread A!"));
Code runs on threads. Objects aren't (generally - see thread local) bound to a particular thread. By doing WinFormControl.Invoke or WPFControl.Invoke, you are posting a message to the Message Pump or Dispatcher respectively, to run some code at a later date.
The message pump is something like this:
Message message;
while(GetMessage(&message))
{
ProcessMessage(message);
}
Microsoft has specifically built their UI controls and projects to allow the posting of messages across threads. Calling a method from thread A will always execute that method on thread A, even if it ends up doing some kind of asynchronous work and returning early.
Edit:
What it is I think you need is the Producer Consumer pattern.
http://msdn.microsoft.com/en-us/library/yy12yx1f(VS.80).aspx
Forget about consuming the messages from your main thread, which is what it sounds like you want to do. Consume from thread C.
Thread A is doing 'much more important things'. Thread B is spinning, listening for messages. Thread C is consuming those messages.
No need for marshalling across threads.
EDIT: I think you probably want to use the System.Threading.AutoResetEvent class. The MSDN documentation has a decent example of one thread waiting on the other that I think is similar to what you are trying to do: http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
In particular, pay attention to the calls to trigger.WaitOne() and trigger.Set()
EDIT2: Added option #3 after reading new comment from OP.
"Whenever I invoke the methods of an object running on thread A ..." - An object doesn't "run" on a thread and isn't really owned by any thread, regardless of what thread created the object.
Given that your question is regarding "non-UI cross-thread invocation", I assume you are already familiar with "UI cross-thread invocation". I can see how WinForms would give you an impression that a thread owns an object and that you need to "send a message" to a thread in order to make it do something.
WinForm control objects are kind of a special case in that they simply don't function properly if you interact with them with a thread that isn't the one that created them, but that's not caused by the way that threads and objects interact.
Anyway, on to addressing your question.
First, a question to clarify the problem: You've mentioned what Thread B is doing, but what is Thread A doing prior to being "invoked" by Thread B?
Here are a couple of ideas that I think are along the lines of what you want to do:
Don't create Thread A until you need to. Instead of having Thread B "send a message to Thread A", rather have Thread B create Thread A (or call it Thread C if you prefer) and make it start executing at that time.
If you need Thread A to already exist and you only want Thread A to handle Thread B's events one at a time, you could have Thread A wait until it receives a notification from Thread B. Take a look at the System.Threading.WaitHandle class (derived classes of interest are ManualResetEvent and AutoResetEvent).
Thread A will at some point call WaitHandle.WaitOne(), which will cause it to pause and wait until Thread B calls WaitHandle.Set() on the same WaitHandle object.
If Thread A is busy doing other things, then you might want to set up some kind of flag variable. Similar to the WaitHandle concept in #2, but instead of causing Thread A to pause, you just want Thread B to set a flag (perhaps just a boolean variable) that will signal to Thread A that it needs to do something. While Thread A is busy doing other things, it can periodically check that flag to decide whether or not there is work that needs to be done.
Does the method that Thread A will execute on your object require any input from Thread B? Then before Thread B calls WaitHandle.Set(), have it stick some data into a queue or something. Then, when Thread A is "activated", it can retrieve that data from the queue and proceed to execute the object's method using that data. Use a lock mechanism (i.e. the C# lock statement) to synchronize access to the queue.
What you're going to have to do is roll a sort of Queue and have Thread A watch that queue for work. When Thread A sees new work enter the queue, it can dequeue it and do the work, then return to waiting for more.
Here's some pseudo-code:
public class ThreadAQueue
{
private Queue<delegate> _queue;
private bool _quitWorking;
public void EnqueueSomeWork(delegate work)
{
lock(_queue)
{
_queue.Enqueue(work);
}
}
private void DoTheWork()
{
while(!quitWorking)
{
delegate myWork;
lock(_queue)
{
if(_queue.Count > 1)
myWork = _queue.Dequeue();
}
myWork();
}
}
}

C# threading pattern that will let me flush

I have a class that implements the Begin/End Invocation pattern where I initially used ThreadPool.QueueUserWorkItem() to thread my work. The work done on the thread doesn't loop but does takes a bit of time to process so the work itself is not easily stopped.
I now have the side effect where someone using my class is calling the Begin (with callback) a ton of times to do a lot of processing so ThreadPool.QueueUserWorkItem is creating a ton of threads to do the processing. That in itself isn't bad but there are instances where they want to abandon the processing and start a new process but they are forced to wait for their first request to finish.
Since ThreadPool.QueueUseWorkItem() doesn't allow me to cancel the threads I am trying to come up with a better way to queue up the work and maybe use an explicit FlushQueue() method in my class to allow the caller to abandon work in my queue.
Anyone have any suggestion on a threading pattern that fits my needs?
Edit: I'm currently targeting the 2.0 framework. I'm currently thinking that a Consumer/Producer queue might work. Does anyone have thoughts on the idea of flushing the queue?
Edit 2 Problem Clarification:
Since I'm using the Begin/End pattern in my class every time the caller uses the Begin with callback I create a whole new thread on the thread pool. This call does a very small amount of processing and is not where I want to cancel. It's the uncompleted jobs in the queue I wish to stop.
The fact that the ThreadPool will create 250 threads per processor by default means if you ask the ThreadPool to queue a large amount of items with QueueUserWorkItem() you end up creating a huge amount of concurrent threads that you have no way of stopping.
The caller is able to push the CPU to 100% with not only the work but the creation of the work because of the way I queued the threads.
I was thinking by using the Producer/Consumer pattern I could queue these threads into my own queue that would allow me to moderate how many threads I create to avoid the CPU spike creating all the concurrent threads. And that I might be able to allow the caller of my class to flush all the jobs in the queue when they are abandoning the requests.
I am currently trying to implement this myself but figured SO was a good place to have someone say look at this code or you won't be able to flush because of this or flushing isn't the right term you mean this.
EDIT My answer does not apply since OP is using 2.0. Leaving up and switching to CW for anyone who reads this question and using 4.0
If you are using C# 4.0, or can take a depedency on one of the earlier version of the parallel frameworks, you can use their built-in cancellation support. It's not as easy as cancelling a thread but the framework is much more reliable (cancelling a thread is very attractive but also very dangerous).
Reed did an excellent article on this you should take a look at
http://reedcopsey.com/2010/02/17/parallelism-in-net-part-10-cancellation-in-plinq-and-the-parallel-class/
A method I've used in the past, though it's certainly not a best practice is to dedicate a class instance to each thread, and have an abort flag on the class. Then create a ThrowIfAborting method on the class that is called periodically from the thread (particularly if the thread's running a loop, just call it every iteration). If the flag has been set, ThrowIfAborting will simply throw an exception, which is caught in the main method for the thread. Just make sure to clean up your resources as you're aborting.
You could extend the Begin/End pattern to become the Begin/Cancel/End pattern. The Cancel method could set a cancel flag that the worker thread polls periodically. When the worker thread detects a cancel request, it can stop its work, clean-up resources as needed, and report that the operation was canceled as part of the End arguments.
I've solved what I believe to be your exact problem by using a wrapper class around 1+ BackgroundWorker instances.
Unfortunately, I'm not able to post my entire class, but here's the basic concept along with it's limitations.
Usage:
You simply create an instance and call RunOrReplace(...) when you want to cancel your old worker and start a new one. If the old worker was busy, it is asked to cancel and then another worker is used to immediately execute your request.
public class BackgroundWorkerReplaceable : IDisposable
{
BackgroupWorker activeWorker = null;
object activeWorkerSyncRoot = new object();
List<BackgroupWorker> workerPool = new List<BackgroupWorker>();
DoWorkEventHandler doWork;
RunWorkerCompletedEventHandler runWorkerCompleted;
public bool IsBusy
{
get { return activeWorker != null ? activeWorker.IsBusy; : false }
}
public BackgroundWorkerReplaceable(DoWorkEventHandler doWork, RunWorkerCompletedEventHandler runWorkerCompleted)
{
this.doWork = doWork;
this.runWorkerCompleted = runWorkerCompleted;
ResetActiveWorker();
}
public void RunOrReplace(Object param, ...) // Overloads could include ProgressChangedEventHandler and other stuff
{
try
{
lock(activeWorkerSyncRoot)
{
if(activeWorker.IsBusy)
{
ResetActiveWorker();
}
// This works because if IsBusy was false above, there is no way for it to become true without another thread obtaining a lock
if(!activeWorker.IsBusy)
{
// Optionally handle ProgressChangedEventHandler and other features (under the lock!)
// Work on this new param
activeWorker.RunWorkerAsync(param);
}
else
{ // This should never happen since we create new workers when there's none available!
throw new LogicException(...); // assert or similar
}
}
}
catch(...) // InvalidOperationException and Exception
{ // In my experience, it's safe to just show the user an error and ignore these, but that's going to depend on what you use this for and where you want the exception handling to be
}
}
public void Cancel()
{
ResetActiveWorker();
}
public void Dispose()
{ // You should implement a proper Dispose/Finalizer pattern
if(activeWorker != null)
{
activeWorker.CancelAsync();
}
foreach(BackgroundWorker worker in workerPool)
{
worker.CancelAsync();
worker.Dispose();
// perhaps use a for loop instead so you can set worker to null? This might help the GC, but it's probably not needed
}
}
void ResetActiveWorker()
{
lock(activeWorkerSyncRoot)
{
if(activeWorker == null)
{
activeWorker = GetAvailableWorker();
}
else if(activeWorker.IsBusy)
{ // Current worker is busy - issue a cancel and set another active worker
activeWorker.CancelAsync(); // Make sure WorkerSupportsCancellation must be set to true [Link9372]
// Optionally handle ProgressEventHandler -=
activeWorker = GetAvailableWorker(); // Ensure that the activeWorker is available
}
//else - do nothing, activeWorker is already ready for work!
}
}
BackgroupdWorker GetAvailableWorker()
{
// Loop through workerPool and return a worker if IsBusy is false
// if the loop exits without returning...
if(activeWorker != null)
{
workerPool.Add(activeWorker); // Save the old worker for possible future use
}
return GenerateNewWorker();
}
BackgroundWorker GenerateNewWorker()
{
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerSupportsCancellation = true; // [Link9372]
//worker.WorkerReportsProgress
worker.DoWork += doWork;
worker.RunWorkerCompleted += runWorkerCompleted;
// Other stuff
return worker;
}
} // class
Pro/Con:
This has the benefit of having a very low delay in starting your new execution, since new threads don't have to wait for old ones to finish.
This comes at the cost of a theoretical never-ending growth of BackgroundWorker objects that never get GC'd. However, in practice the code below attempts to recycle old workers so you shouldn't normally encounter a large pool of ideal threads. If you are worried about this because of how you plan to use this class, you could implement a Timer which fires a CleanUpExcessWorkers(...) method, or have ResetActiveWorker() do this cleanup (at the cost of a longer RunOrReplace(...) delay).
The main cost from using this is precisely why it's beneficial - it doesn't wait for the previous thread to exit, so for example, if DoWork is performing a database call and you execute RunOrReplace(...) 10 times in rapid succession, the database call might not be immediately canceled when the thread is - so you'll have 10 queries running, making all of them slow! This generally tends to work fine with Oracle, causing only minor delays, but I do not have experiences with other databases (to speed up the cleanup, I have the canceled worker tell Oracle to cancel the command). Proper use of the EventArgs described below mostly solves this.
Another minor cost is that whatever code this BackgroundWorker is performing must be compatible with this concept - it must be able to safely recover from being canceled. The DoWorkEventArgs and RunWorkerCompletedEventArgs have a Cancel/Cancelled property which you should use. For example, if you do Database calls in the DoWork method (mainly what I use this class for), you need to make sure you periodically check these properties and take perform the appropriate clean-up.

Categories

Resources