I'm trying to learn threading on C# but have got a bit stuck on how to handle properties.
Take for example my class NavigateIE which can only carry out a single action at a time. I thought if I had a property busy then I would know if the instance was busy outside the class.
class NavigateIE
{
public bool busy;
public void IEAction(string action)
{
busy = true;
var th = new Thread(() =>
{
try
{
//Do stuff
}
catch(Exception ex)
{
//report Exception
}
finally
{
busy = false;
}
});
th.SetApartmentState(ApartmentState.STA);
th.Start();
}
}
However, as busy = false; is only ever called inside the thread then this doesn't work as navigateIE.busy is always true.
class MainElsewhere
{
private NavigateIE navigateIE = new NavigateIE();
private void Main()
{
if (!navigateIE.busy)
{
//navigateIE.busy always == true
}
}
}
I have 2 questions:
1) How do I set up the property so it's threadsafe and busy = false; is seen outside the class?
2) Is there a better way to do this?
Edit: Essentially NavigateIE is a class to handle a single instance of IE using Watin. I can only call a method in NavigateIE if there are no other methods running otherwsie a previous action has not completed. NavigateIE is called from a main method that is on a timer tick, hence why I need to check if the class is busy.
navigateIE.busy == false the first time but after the thread sets it back to false the main method still sees navigateIE.busy == true.
You are doing this fundamentally wrong. Yes, busy is pretty likely to be true, that thread will start running quickly on a modern multi-core processor. No actual guarantee, it is merely very common. Exactly when it turns back to false is highly unpredictable as well, depends what the thread does. Including never, a bool is not a synchronization primitive.
It is not clear to me what you are trying to achieve, but you don't actually need to use a busy flag at all. IE is an apartment-threaded COM object, it already automatically marshals the call to the STA thread that owns the object. Calling its Navigate() method from another thread is fine, no extra code is required to help. If you need a busy flag to indicate that the browser is working on a command then you'll need a flag that you set to true when you actually start navigating instead of when you start the thread. Leverage the code in this answer, perhaps.
I started to write an answer, but there are just a lot of variables here. (you should be locking, but really signalling might be a better solution, etc). I really think that rather than throwing a code snippet at you, a better answer would be do direct you to do a little more digging on .net threading.
Here's an ebook that might be helpful for you: http://www.albahari.com/threading/
How do I set up the property so [..] busy = false; is seen outside the class?
Your example doesn't work because busy needs to be marked volatile
Is there a better way to do this?
It sounds like all calls within NavigateIE always need to be serialized. If that's true, I would just put a lock statement in each thread-call
public object mutex = new object();
public void IEAction(string action)
{
var th = new Thread(() =>
{
lock(mutex)
{
//Serialzed code goes here
}
});
//etc.
}
Also, note that you rarely want to actually create your own Thread instance - you should either be using a BackgroundWorker, obtaining a thread from the ThreadPool, or using the new Tasks Parallel Library (TPL).
If you're unsure, the TPL is usually the best place to start.
Related
I create a plugin for an application.
When a user presses a stop command in the parent application, a global variable to which my plugin has access to is set to true.
For a simple method I create, I test this variable and exit:
public class Status
{
public static bool CheckTermFlag()
{
if (VoiceAttackPlugin._stopVariableToMonitor)
{
VoiceAttackPlugin._stopVariableToMonitor = false;
return true;
}
return false;
}
}
And I place this 'CheckTermFlag' in my code:
class ForTesting
{
public static void SendStopAllTest()
{
for (int i = 0; i <= 20; i++)
{
if (Status.CheckTermFlag())
{
return;
}
Thread.Sleep(500);
vaProxy.WriteToLog(i.ToString(), "Green");
}
}
The problem is that I may have several methods and each calling another one.
I can't place a question for "Status.CheckTermFlag()" in every step of my program and propagate it upwards.
So how can i 'listen' for this variable from anywhere in my program and terminate/return if required?
Why not use a CancellationToken for this? You can stop any method by any method that way. If a method have access to CTS it can just call Cancel and all methods that have CancellationTokens can then finish whatever they are doing and exit.
In multithreading environment a SemaphoreSlim can be used as an awaitable reset event as a mean of synchronizing threads.
I wouldn't use Thread.Abort(), it's good for the threads you have no control over. But if it's all your code and you control it - it's always better just to signal between threads and ask them nicely to terminate, that leads to less undefined states and behaviors later.
BTW, just make either the CancellationTokenSource accessible to methods that should stop the calling method, or made an accessible method that calls Cancel() on CTS. I used that approach a lot in a high-load network gateway and a desktop application that downloaded a large number of files parallelly. The cost of it is negligible. Don't be afraid of disposables, used correctly they save more time than it takes to handle them.
In a multi-threaded scenario the way to go is the Thread.Abort() method. It throws the ThreadAbortException in the target thread, causing it to terminate.
If you, for whatever reason, need a custom solution, do it likewise. Throw an exception, and handle it at the top-most method where it makes sense. Like this:
public class TerminateProcessingExeption : Exception { … }
…
public static bool CheckTermFlag()
{
if (VoiceAttackPlugin._stopVariableToMonitor)
{
VoiceAttackPlugin._stopVariableToMonitor = false;
throw new TerminateProcessingExeption();
}
}
In addition, instead of a bool flag, consider using an AutoResetEvent. Look into the example in the documentation for more information. A simple variable won't shield you from the adverse effects of concurrent memory access in multi-processor setups.
I have the following code running in a Windows form. The method it is calling takes about 40 seconds to complete, and I need to allow the user the ability to click an 'Abort' button to stop the thread running.
Normally I would have the Worker() method polling to see if the _terminationMessage was set to "Stop" but I can't do this here because the long running method, ThisMethodMightReturnSomethingAndICantChangeIt() is out of my control.
How do I implement this user feature please ?
Here is my thread code.
private const string TerminationValue = "Stop";
private volatile string _terminationMessage;
private bool RunThread()
{
try
{
var worker = new Thread(Worker);
_terminationMessage = "carry on";
_successful = false;
worker.Start();
worker.Join();
finally
{
return _successful;
}
}
private void Worker()
{
ThisMethodMightReturnSomethingAndICantChangeIt();
_successful = true;
}
Well, the simple answer would be "you can't". There's no real thread abort that you can use to cancel any processing that's happenning.
Thread.Abort will allow you to abort a managed thread, running managed code at the moment, but it's really just a bad idea. It's very easy to end up in an inconsistent state just because you were just now running a singleton constructor or something. In the end, there's quite a big chance you're going to blow something up.
A bit orthogonal to the question, but why are you still using threading code like this? Writing multi-threaded code is really hard, so you want to use as many high-level features as you can. The complexity can easily be seen already in your small snippet of code - you're Joining the newly created thread, which means that you're basically gaining no benefit whatsoever from starting the Worker method on a new thread - you start it, and then you just wait. It's just like calling Worker outright, except you'll save an unnecessary thread.
try will not catch exceptions that pop up in a separate thread. So any exception that gets thrown inside of Worker will simply kill your whole process. Not good.
The only way to implement reliable cancellation is through cooperative aborts. .NET has great constructs for this since 4.0, CancellationToken. It's easy to use, it's thread-safe (unlike your solution), and it can be propagated through all the method chain so that you can implement cancellation at depth. Sadly, if you simply can't modify the ThisMethodMightReturnSomethingAndICantChangeIt method, you're out of luck.
The only "supported" "cancellation" pattern that just works is Process.Kill. You'd have to launch the processing method in a wholy separate process, not just a separate thread. That can be killed, and it will not hurt your own process. Of course, it means you have to separate that call into a new process - that's usually quite tricky, and it's not a very good design (though it seems like you have little choice).
So if the method doesn't support some form of cancellation, just treat it like so. It can't be aborted, period. Any way that does abort it is a dirty hack.
Well, here's my solution so far. I will definitely read up on newer .NET higher level features as you suggest. Thanks for the pointers in the right direction
private void RunThread()
{
try
{
var worker = new Thread(Worker);
SetFormEnabledStatus(false);
_usuccessful = false;
worker.Start();
// give up if no response before timeout
worker.Join(60000); // TODO - Add timeout to config
worker.Abort();
}
finally
{
SetFormEnabledStatus(true);
}
}
private void Worker()
{
try
{
_successful= false;
ThisMethodMightReturnSomethingAndICantChangeIt();
_successful = true;
}
catch (ThreadAbortException ex)
{
// nlog.....
}
catch (Exception ex)
{
// nlog...
}
}
From what I can tell I have misleading bits of information. I need to have a separate thread running in the background.
At the moment I do it like this:
var task = Task.Factory.StartNew
(CheckFiles
, cancelCheckFile.Token
, TaskCreationOptions.LongRunning
, TaskScheduler.Default);//Check for files on another thread
private void CheckFiles()
{
while (!cancelCheckFile.Token.IsCancellationRequested)
{
//do stuff
}
}
This always creates a new thread for me. However after several discussions even if it is marked as LongRunning doesn't guarantee that a new thread will be created.
In the past I have done something like this:
thQueueChecker = new Thread(new ThreadStart(CheckQueue));
thQueueChecker.IsBackground = true;
thQueueChecker.Name = "CheckQueues" + DateTime.Now.Ticks.ToString();
thQueueChecker.Start();
private void CheckQueue()
{
while (!ProgramEnding)
{
//do stuff
}
}
Would you recommend that I go back to this approach to guarantee a new thread is used?
The default task scheduler ThreadPoolTaskScheduler does indeed always create a new thread for long running task. It does not use the thread pool as you can see. It is no different as the manual approach to create the thread by yourself. In theory it could happen that the thread scheduler of .NET 4.5 does something different but in practice it is unlikely to change.
protected internal override void QueueTask(Task task)
{
if ((task.Options & TaskCreationOptions.LongRunning) != TaskCreationOptions.None)
{
new Thread(s_longRunningThreadWork) { IsBackground = true }.Start(task);
}
else
{
bool forceGlobal =
(task.Options & TaskCreationOptions.PreferFairness) != TaskCreationOptions.None;
ThreadPool.UnsafeQueueCustomWorkItem(task, forceGlobal);
}
}
It depends on the Scheduler you use. There are two stock implementations, ThreadPoolTaskScheduler and SynchronizationContextTaskScheduler. The latter doesn't start a thread at all, used by the FromCurrentSynchronizationContext() method.
The ThreadPoolTaskScheduler is what you get. Which indeed uses the LongRunning option, it will use a regular Thread if it set. Important to avoid starving other TP threads. You'll get a TP thread without the option. These are implementation details subject to change without notice, although I'd consider it unlikely anytime soon.
LongRunning is just a hint to the scheduler - if you absolutely must always have a new Thread, you will have to create one.
You'll have to specify why you "always need a separate thread".
void Main()
{
var task = Task.Factory.StartNew(CheckFiles,
cancelCheckFile.Token,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
task.Wait();
}
A smart scheduler will use 1 thread here. Why shouldn't it?
But in general the CheckFiles() method will be executed on another (than the calling) thread. The issue is whether that thread is especially created or whether it might even be executed on several threads (in succession).
When you are using Tasks you give up control over the Thread. And that should be a good thing.
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.
I need to do a sort of "timeout" or pause in my method for 10 seconds (10000 milliseconds), but I'm not sure if the following would work as i do not have multi-threading.
Thread.Sleep(10000);
I will try to use that current code, but I would appreciate if someone could explain the best and correct way of doing this, especially if the above code does not work properly. Thanks!
UPDATE: This program is actually a console application that in the function in question is doing many HTTPWebRequests to one server, so I wish to delay them for a specified amount of milliseconds. Thus, no callback is required - all that is needed is an "unconditional pause" - basically just the whole thing stops for 10 seconds and then keeps going. I'm pleased that C# still considers this as a thread, so Thread.Sleep(...) would work. Thanks everybody!
You may not have multi-threading, but you're still executing within a thread: all code executes in a thread.
Calling Thread.Sleep will indeed pause the current thread. Do you really want it to unconditionally pause for 10 seconds, or do you want to be able to be "woken up" by something else happening? If you're only actually using one thread, calling Sleep may well be the best way forward, but it will depend on the situation.
In particular, if you're writing a GUI app you don't want to use Thread.Sleep from the UI thread, as otherwise your whole app will become unresponsive for 10 seconds.
If you could give more information about your application, that would help us to advise you better.
Thread.Sleep is fine, and AFAIK the proper way. Even if you are not Multithreaded: There is always at least one Thread, and if you send that to sleep, it sleeps.
Another (bad) way is a spinlock, something like:
// Do never ever use this
private void DoNothing(){ }
private void KillCPU()
{
DateTime target = DateTime.Now.AddSeconds(10);
while(DateTime.Now < target) DoNothing();
DoStuffAfterWaiting10Seconds();
}
This is sadly still being used by people and while it will halt your program for 10 seconds, it will run at 100% CPU Utilization (Well, on Multi-Core systems it's one core).
That will indeed pause the executing thread/method for 10 seconds. Are you seeing a specific problem?
Note that you shouldn't Sleep the UI thread - it would be better to do a callback instead.
Note also that there are other ways of blocking a thread that allow simpler access to get it going again (if you find it is OK after 2s); such as Monitor.Wait(obj, 10000) (allowing another thread to Pulse if needed to wake it up):
static void Main() {
object lockObj = new object();
lock (lockObj) {
new Thread(GetInput).Start(lockObj);
Monitor.Wait(lockObj, 10000);
}
Console.WriteLine("Main exiting");
}
static void GetInput(object state) {
Console.WriteLine("press return...");
string s = Console.ReadLine();
lock (state) {
Monitor.Pulse(state);
}
Console.WriteLine("GetInput exiting");
}
You can do this with Thread.Interrupt too, but IMO that is messier.
You could use a separate thread to do it:
ThreadPool.QueueUserWorkItem(
delegate(object state)
{
Thread.Sleep(1000);
Console.WriteLine("done");
});
But, if this is a Windows Forms app, you will need to invoke the code after the delay from the Gui thread (this article, for example: How to update the GUI from another thread in C#?).
[Edit] Just saw your update. If it's a console app, then this will work. But if you haven't used multiple threads so far, then you need to be aware that this code will be executed in a different thread, which means you will have to take care about thread synchronization issues.
If you don't need background workers, stick to "keeping it simple".
Here is a pause class that will pause for the desired milliseconds and wont consume your CPU resources.
public class PauseClass
{
//(C) Michael Roberg
//Please feel free to distribute this class but include my credentials.
System.Timers.Timer pauseTimer = null;
public void BreakPause()
{
if (pauseTimer != null)
{
pauseTimer.Stop();
pauseTimer.Enabled = false;
}
}
public bool Pause(int miliseconds)
{
ThreadPriority CurrentPriority = Thread.CurrentThread.Priority;
if (miliseconds > 0)
{
Thread.CurrentThread.Priority = ThreadPriority.Lowest;
pauseTimer = new System.Timers.Timer();
pauseTimer.Elapsed += new ElapsedEventHandler(pauseTimer_Elapsed);
pauseTimer.Interval = miliseconds;
pauseTimer.Enabled = true;
while (pauseTimer.Enabled)
{
Thread.Sleep(10);
Application.DoEvents();
//pausThread.Sleep(1);
}
pauseTimer.Elapsed -= new ElapsedEventHandler(pauseTimer_Elapsed);
}
Thread.CurrentThread.Priority = CurrentPriority;
return true;
}
private void pauseTimer_Elapsed(object sender, ElapsedEventArgs e)
{
pauseTimer.Enabled = false;
}
}
Yes, that works just fine.
You don't have to have multiple threads to make use of some of the methods in the Thread class. You always have at least one thread.
For a timeout, you should have a static volatile boolean isRunning class field. When the new thread starts, the isRunning must become true, and at the end must become false.
The main thread should have a method that loops for the isRunning during the timeout you define. When the timeout ends, you should implement the logic. But, never use the abort thread method.
A pause... there isn't a straightforward solution. It depends on what you are doing inside the thread. However, you could look at Monitor.Wait.
If you can have an async method, you can do something like to pause the function at a certain location. Once pause is set false it will continue executing the rest of the code in the method. Since this is an async method and delay is async too UI execution wouldn't be affected.
* Please note that asyn is supported only in .net 4.5 and higher.
bool pause = true;
void async foo()
{
//some code
while (pause)
{
await Task.Delay(100);
}
//some code
}