I have a thread. At a certain point, what I want to do is check if a certain lock is free. If it is free, I want the thread to continue on its merry way. If it is not free, I want to wait until it is free, but then not actually acquire the lock.
Here is my code so far:
private object LockObject = new Object();
async void SlowMethod() {
lock (LockObject) {
// lotsa stuff
}
}
void AppStartup() {
this.SlowMethod();
UIThreadStartupStuff();
// now, I want to wait on the lock. I don't know where/how the results
// of SlowMethod might be needed. But I do know that they will be needed.
// And I don't want to check the lock every time.
}
I think you have classical XY problem. I guess what you want is start a Task with you SlowMethod and then Continue it with the UIThreadStartupStuff is UI thread.
Task.Factory.StartNew(()=>SlowMethod())
.ContinueWith(t=>UIThreadStartupStuff(), TaskScheduler.FromCurrentSynchronizationContext());
or with async/await (make your SlowMethod to return Task)
try
{
await SlowMethod();
}
catch(...)
{}
UIThreadStartupStuff();
You don't want to use a lock here. You need an event. Either ManualResetEvent or AutoResetEvent.
Remember, locks are used for mutual exclusion. Events are used for signaling.
You have your SlowMethod set the event when it's done. For example:
private ManualResetEvent DoneEvent = new ManualResetEvent(false);
async void SlowMethod() {
// lotsa stuff
// done with lotsa stuff. Signal the event.
DoneEvent.Set();
}
void AppStartup() {
this.SlowMethod();
UIThreadStartupStuff();
// Wait for the SlowMethod to set the event:
DoneEvent.WaitOne();
}
I might not get what you want to achieve, but why not wait on the lock "properly"?
After all, it is a clear sign of the lock being free if you can take it.
Also, you can release it immediately if it is important.
void AppStartup() {
this.SlowMethod();
UIThreadStartupStuff();
// now, I want to wait on the lock. I don't know where/how the results
// of SlowMethod might be needed. But I do know that they will be needed.
// And I don't want to check the lock every time.
lock (LockObject) {
// nothing, you now know the lock was free
}
// continue...
}
Related
i know the common ways of cancelling a backgroundworker using eventwaithandles...
but i wanna know is that right to use a while loop to trap and pause working of a backgroundworker ? i coded like this :
Bool stop = false;
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
progressBar1.Minimum = 0;
progressBar1.Maximum = 100000;
progressBar1.Value = 0;
for (int i = 0; i < 100000; i++)
{
progressBar1.Value++;
if (i == 50000)
stop = true;
while (stop)
{ }
}
}
private void button1_Click(object sender, EventArgs e)
{
stop = !stop;
}
Did you try it? What happened? Was it what you wanted to happen? Did you notice your computer's fans speeding up, to handle all the heat from your CPU in a tight, "do-nothing" loop?
Fact is, you should not "pause" a background task in the first place; if you don't it to keep running, interrupt it. If you want to be able to resume later, provide a mechanism to allow that. Even having your thread blocked efficiently waiting on a WaitHandle object would be the wrong thing to do, because it wastes a thread pool thread.
The code you've posted here is about the worst way to implement "pausing". Instead of waiting on some synchronization object such as a WaitHandle, you have the current thread just loop without interrupting, constantly checking the value of a flag. Even ignoring the question of whether you're using volatile (the code example doesn't show that, but then it also wouldn't compile, so…), it's terrible to force a CPU core to do so much work and yet get nowhere.
Don't pause your BackgroundWorker.DoWork handler in the first place. Really. Just don't do that. But if you insist, then at least use some kind of waitable object instead of a "spin-wait" loop as in the example you've posted here.
Here's an example of how your code might work if you wanted to avoid altogether tying up a thread while "paused". First, don't use BackgroundWorker, because it doesn't have a graceful way to do this. Second, do use await…that does specifically what you want: it allows the current method to return, but without losing track of its progress. The method will resume executing when the thing it waited on indicates completion.
In the example below, I've tried to guess at what the code that calls RunWorkerAsync() looks like. Or rather, I just assumed you've got a button2, which when clicked you call that method to start your worker task. If this is not enough to get you pointed in the right direction, please improve your question by including a good, minimal, complete code example showing what you're actually doing.
// These fields will work together to provide a way for the thread to interrupt
// itself temporarily without actually using a thread at all.
private TaskCompletionSource<object> _pause;
private readonly object _pauseLock = new object();
private void button2_Click(object sender, DoWorkEventArgs e)
{
// Initialize ProgressBar. Note: in your version of the code, this was
// done in the DoWork event handler, but that handler isn't executed in
// the UI thread, and so accessing a UI object like progressBar1 is not
// a good idea. If you got away with it, you were lucky.
progressBar1.Minimum = 0;
progressBar1.Maximum = 100000;
progressBar1.Value = 0;
// This object will perform the duty of the BackgroundWorker's
// ProgressChanged event and ReportProgress() method.
Progress<int> progress = new Progress<int>(i => progressBar1.Value++);
// We do want the code to run in the background. Use Task.Run() to accomplish that
Task.Run(async () =>
{
for (int i = 0; i < 100000; i++)
{
progress.Report(i);
Task task = null;
// Locking ensures that the two threads which may be interacting
// with the _pause object do not interfere with each other.
lock (_pauseLock)
{
if (i == 50000)
{
// We want to pause. But it's possible we lost the race with
// the user, who also just pressed the pause button. So
// only allocate a new TCS if there isn't already one
if (_pause == null)
{
_pause = new TaskCompletionSource<object>();
}
}
// If by the time we get here, there's a TCS to wait on, then
// set our local variable for the Task to wait on. In this way
// we resolve any other race that might occur between the time
// we checked the _pause object and then later tried to wait on it
if (_pause != null)
{
task = _pause.Task;
}
}
if (task != null)
{
// This is the most important part: using "await" tells the method to
// return, but in a way that will allow execution to resume later.
// That is, when the TCS's Task transitions to the completed state,
// this method will resume executing, using any available thread
// in the thread pool.
await task;
// Once we resume execution here, reset the TCS, to allow the pause
// to go back to pausing again.
lock (_pauseLock)
{
_pause.Dispose();
_pause = null;
}
}
}
});
}
private void button1_Click(object sender, EventArgs e)
{
lock (_pauseLock)
{
// A bit more complicated than toggling a flag, granted. But it achieves
// the desirable goal.
if (_pause == null)
{
// Creates the object to wait on. The worker thread will look for
// this and wait if it exists.
_pause = new TaskCompletionSource<object>();
}
else if (!_pause.Task.IsCompleted)
{
// Giving the TCS a result causes its corresponding Task to transition
// to the completed state, releasing any code that might be waiting
// on it.
_pause.SetResult(null);
}
}
}
Note that the above is just as contrived as your original example. If all you had really was a simple single loop variable iterating from 0 to 100,000 and stopping halfway through, nothing nearly so complicated as the above would be required. You'd just store the loop variable in a data structure somewhere, exit the running task thread, and then when you want to resume, pass in the current loop variable value so the method can resume at the right index.
But I'm assuming your real-world example is not so simple. And the above strategy will work for any stateful processing, with the compiler doing all the heavy-lifting of storing away intermediate state for you.
I'm still unsure on the differences between these two calls. From MSDN,
Monitor.Enter(Object) Acquires an exclusive lock on the specified object.
Monitor.Wait(Object) Releases the lock on an object and blocks the current thread until it reacquires the lock.
From that I assume that Monitor.Wait is the same as Monitor.Enter except that it releases the lock on the object first before reacquiring.
Does the current thread have to have the lock in the first place? How could a different thread force a release on a lock of an object? Why would the same thread want to reacquire a lock?
According to MSDN: Monitor.Wait Method(Object)
SynchronizationLockException: The calling thread does not own the lock for the specified object.
In other words: You can only call Monitor.Wait(Object), when you already own the lock, whereas you call Monitor.Enter(Object) in order to acquire the lock.
As for why Monitor.Wait is needed: If your thread realizes, that it is lacking information to continue execution (e.g. it's waiting for a signal), you might want to let other threads enter the critical section, because not all threads have the same prerequisites.
For the waiting thread to continue execution, you will need to call Monitor.Pulse(Object) or Monitor.PulseAll(Object) before releasing the lock (otherwise, you're going to get the same kind of exception as with Monitor.Wait(Object)).
Keep in mind, that the next thread that acquires the lock after a pulse and after the lock was released, is not necessarily the thread that received the pulse.
Also keep in mind, that receiving a pulse, is not equivalent to having your condition met. You might still need to wait just a little longer:
// make sure to synchronize this correctly ;)
while (ConditionNotMet)
{
Monitor.Wait(mutex);
if (ConditionNotMet) // We woke up, but our condition is still not met
Monitor.Pulse(mutex); // Perhaps another waiting thread wants to wake up?
}
Consider this example:
public class EnterExitExample
{
private object myLock;
private bool running;
private void ThreadProc1()
{
while (running)
{
lock (myLock)
{
// Do stuff here...
}
Thread.Yield();
}
}
private void ThreadProc2()
{
while (running)
{
lock (myLock)
{
// Do other stuff here...
}
Thread.Yield();
}
}
}
Now you have two threads, each waiting for lock, then doing their stuff, then releasing the lock. The lock (myLock) syntax is just sugar for Monitor.Enter(myLock) and Monitor.Exit(myLock).
Let us now look at a more complicated example, where Wait and Pulse come into play.
public class PulseWaitExample
{
private Queue<object> queue;
private bool running;
private void ProducerThreadProc()
{
while (running)
{
object produced = ...; // Do production stuff here.
lock (queue)
{
queue.Enqueue(produced);
Monitor.Pulse(queue);
}
}
}
private void ConsumerThreadProc()
{
while (running)
{
object toBeConsumed;
lock (queue)
{
Monitor.Wait(queue);
toBeConsumed = queue.Dequeue();
}
// Do consuming stuff with toBeConsumed here.
}
}
}
What do we have here?
The producer produces an object whenever he feels like it. As soon as he has, he obtains lock on the queue, enqueues the object, then does a Pulse call.
At the same time, the consumer does NOT have lock, he left it by calling Wait. As soon as he gets a Pulse on that object, he will re-lock, and do his consuming stuff.
So what you have here is a direct thread-to-thread notification that there is something to do for the consumer. If you wouldn't have that, all you could do is have the consumer keep polling on the collection if there is something to do yet. Using Wait, you can make sure that there is.
As Cristi mentioned, a naive wait/pulse code does not work. Because your are completely missing the crucial point here : The monitor is NOT a message queue. If you pulse and no one is waiting, the pulse is LOST.
The right philosophy is that your are waiting for a condition, and if the condition is not satisfied, there is a way to wait for it, without eating cpu and without holding the lock. Here, the condition for the consumer is that there is something in the queue.
See https://ideone.com/tWqTS1 which work (a fork from by Cristi's example).
public class PulseWaitExample
{
private Queue<object> queue;
private bool running;
private void ProducerThreadProc()
{
while (running)
{
object produced = ...; // Do production stuff here.
lock (queue)
{
queue.Enqueue(produced);
Monitor.Pulse(queue);
}
}
}
private void ConsumerThreadProc()
{
while (running)
{
object toBeConsumed;
lock (queue)
{
// here is the fix
if (queue.Count == 0)
{
Monitor.Wait(queue);
}
toBeConsumed = queue.Dequeue();
}
// Do consuming stuff with toBeConsumed here.
}
}
}
I have a worker thread that may be active for short bursts of time and idle for rest of the time. I'm thinking to put the thread to sleep and then awake it when needed.
Any additional recommendations for this I should be aware of?
Thanks!
this is in C#/.NET4
You should probably not be using a persistent worker thread- use the thread pool. This is exactly what it is intended for.
ThreadPool.QueueUserWorkItem(() => {
// My temporary work here
});
If you insist on having a persistent worker thread, make it run this:
// This is our latch- we can use this to "let the thread out of the gate"
AutoResetEvent threadLatch = new AutoResetEvent(false);
// The thread runs this
public void DoBackgroundWork() {
// Making sure that the thread is a background thread
// ensures that the endless loop below doesn't prevent
// the program from exiting
Thread.IsBackground = true;
while (true) {
// The worker thread will get here and then block
// until someone Set()s the latch:
threadLatch.WaitOne();
// Do your work here
}
}
// To signal the thread to start:
threadLatch.Set();
Also note that if this background thread is going to interact with the user interface at all, you'll need to Invoke or BeginInvoke accordingly. See http://weblogs.asp.net/justin_rogers/pages/126345.aspx
Just use an event to pause the worker thread: reset - paused, set - unpaused (working) state.
Here is the draft version of code that demonstrates the approach.
class Worker
{
private Thread _thread;
// Un-paused by default.
private ManualResetEvent _notToBePaused = new ManualResetEvent(true);
public Worker()
{
_thread = new Thread(Run)
{
IsBackground = true
};
}
/// <summary>
/// Thread function.
/// </summary>
private void Run()
{
while (true)
{
// Would block if paused!
_notToBePaused.WaitOne();
// Process some stuff here.
}
}
public void Start()
{
_thread.Start();
}
public void Pause()
{
_notToBePaused.Reset();
}
public void UnPause()
{
_notToBePaused.Set();
}
}
Signaling with WaitHandle is the right way to go, but just to add on what others said already
I'd usually go with 2 signals working together, otherwise you wouldn't know whether to 'continue' or 'exit' when needed - or would have to resort to a less graceful way of doing that (stopping the thread - of course there are other ways of doing something like this, just one 'pattern'). So usually it works with an 'exit' signal and a 'new work available' signal - working in unison. e.g.
WaitHandle[] eventArray = new WaitHandle[2] { _exitEvent, _newWorkEvent };
while ((waitid = WaitHandle.WaitAny(eventArray, timeout, false)) > 1)
{
// do your work, and optionally handle timeout etc.
}
note:
exit is ManualResetEvent with 'false' initial state - 'Set' event to exit.
_newWork is either Manual in which case you need to pause/continue from outside which is what you wanted I think -
...or could also be new AutoResetEvent(false) which you 'signal' to do one loop of work, signal returns to 'false' right away - and you need to repeat that for each 'new batch' of work - this is a bit simplified.
(often that goes hand in hand with some 'messages' being passed along, synchronized of course in some way).
Hope this adds some more info,
i'm newbie in c#. I need to obtain lock in 2 methods, but release in one method. Will that work?
public void obtainLock() {
Monitor.Enter(lockObj);
}
public void obtainReleaseLock() {
lock (lockObj) {
doStuff
}
}
Especially can I call obtainLock and then obtainReleaseLock? Is "doubleLock" allowed in C#? These two methods are always called from the same thread, however lockObj is used in another thread for synchronization.
upd: after all comments what do you think about such code? is it ideal?
public void obtainLock() {
if (needCallMonitorExit == false) {
Monitor.Enter(lockObj);
needCallMonitorExit = true;
}
// doStuff
}
public void obtainReleaseLock() {
try {
lock (lockObj) {
// doAnotherStuff
}
} finally {
if (needCallMonitorExit == true) {
needCallMonitorExit = false;
Monitor.Exit(lockObj);
}
}
}
Yes, locks are "re-entrant", so a call can "double-lock" (your phrase) the lockObj. however note that it needs to be released exactly as many times as it is taken; you will need to ensure that there is a corresponding "ReleaseLock" to match "ObtainLock".
I do, however, suggest it is easier to let the caller lock(...) on some property you expose, though:
public object SyncLock { get { return lockObj; } }
now the caller can (instead of obtainLock()):
lock(something.SyncLock) {
//...
}
much easier to get right. Because this is the same underlying lockObj that is used internally, this synchronizes against either usage, even if obtainReleaseLock (etc) is used inside code that locked against SyncLock.
With the context clearer (comments), it seems that maybe Wait and Pulse are the way to do this:
void SomeMethodThatMightNeedToWait() {
lock(lockObj) {
if(needSomethingSpecialToHappen) {
Monitor.Wait(lockObj);
// ^^^ this ***releases*** the lock (however many times needed), and
// enters the pending-queue; when *another* thread "pulses", it
// enters the ready-queue; when the lock is *available*, it
// reacquires the lock (back to as many times as it held it
// previously) and resumes work
}
// do some work, happy that something special happened, and
// we have the lock
}
}
void SomeMethodThatMightSignalSomethingSpecial() {
lock(lockObj) {
// do stuff
Monitor.PulseAll(lockObj);
// ^^^ this moves **all** items from the pending-queue to the ready-queue
// note there is also Pulse(...) which moves a *single* item
}
}
Note that when using Wait you might want to use the overload that accepts a timeout, to avoid waiting forever; note also it is quite common to have to loop and re-validate, for example:
lock(lockObj) {
while(needSomethingSpecialToHappen) {
Monitor.Wait(lockObj);
// at this point, we know we were pulsed, but maybe another waiting
// thread beat us to it! re-check the condition, and continue; this might
// also be a good place to check for some "abort" condition (and
// remember to do a PulseAll() when aborting)
}
// do some work, happy that something special happened, and we have the lock
}
You would have to use the Monitor for this functionality. Note that you open yourself up to deadlocks and race conditions if you aren't careful with your locks and having them taken and released in seperate areas of code can be risky
Monitor.Exit(lockObj);
Only one owner can hold the lock at a given time; it is exclusive. While the locking can be chained the more important component is making sure you obtain and release the proper number of times, avoiding difficult to diagnose threading issues.
When you wrap your code via lock { ... }, you are essentially calling Monitor.Enter and Monitor.Exit as scope is entered and departed.
When you explicitly call Monitor.Enter you are obtaining the lock and at that point you would need to call Monitor.Exit to release the lock.
This doesn't work.
The code
lock(lockObj)
{
// do stuff
}
is translated to something like
Monitor.Enter(lockObj)
try
{
// do stuff
}
finally
{
Monitor.Exit(lockObj)
}
That means that your code enters the lock twice but releases it only once. According to the documentation, the lock is only really released by the thread if Exit was called as often as Enter which is not the case in your code.
Summary: Your code will not deadlock on the call to obtainReleaseLock, but the lock on lockObj will never be released by the thread. You would need to have an explicit call to Monitor.Exit(lockObj), so the calls to Monitor.Enter matches the number of calls to Monitor.Exit.
I tried the following (pseudocode) but I always get a deadlock when Iam trying to stop my thread.
The problem is that Join() waits for the thread to complete and a pending Invoke() operation is also waiting to complete. How can I solve this?
Thread workerThread = new Thread(BackupThreadRunner);
volatile bool cancel;
// this is the thread worker routine
void BackupThreadRunner()
{
while (!cancel)
{
DoStuff();
ReportProgress();
}
}
// main thread
void ReportProgress()
{
if (InvokeRequired)
{
Invoke(ReportProgress);
}
UpdateStatusBarAndStuff();
}
// main thread
void DoCancel()
{
cancel=true;
workerThread.Join();
}
You could use BeginInvoke(ReportProgress) - that way your worker thread doesn't have to wait for the UpdateStatusBarAndStuff method to finish.
use `BeginInvoke' instead
I would do it a slightly different way:
private Thread workerThread;
void StartButtonClick()
{
workerThread = new Thread(ReportProgress);
thread.Start();
}
void CancelButtonClick()
{
// If you use a while(bool), it will repeat the task forever
// or with no while and just a bool, you'll have to check the value of the bool in each line
// so simply aborting it (providing you clean up) is accceptable.
workerThread.Abort();
// If you don't mind your user waiting:
// workerThread.Join(1000);
}
void ReportProgress()
{
if (InvokeRequired)
{
Invoke(ReportProgress);
return;
}
UpdateStatusBarAndStuff();
}
The best practice advice is "don't abort". This is based on the fact you don't know at what point the abort call will exit your code - it could be half way through creating a Stream. So you end up with a choice: can you guarantee that at whatever line the code exits, it will be in a reasonable state to do so?
If you can't then you will need to use a Thread.Join().
Even with a Thread.Join, the user may get bored and quit (ALT+F4) the app, and you have exactly the same situation as you had with the Thread.Abort() call.