Terminate parent method from child method - c#

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.

Related

How to check if another thread is within a locked section, using AsyncEx?

I've just started using Nito.AsyncEx package and AsyncLock instead of a normal lock() { ... } section where I have async calls within the locked section (since you can't use lock() in such cases for good reasons I've just read about). This is within a job that I'm running from Hangfire. Let's call this the 'worker' thread.
In another thread, from an ASP.NET controller, I'd like to check if there's a thread that's currently executing within the locked section. If there's no thread in the locked section then I'll schedule a background job via Hangfire. If there's already a thread in the locked section then I don't want to schedule another one. (Yes, this might sound a little weird, but that's another story).
Is there a way to check this using the Nito.AsyncEx objects, or should I just set a flag at the start of the locked section and unset it at the end?
e.g. I'd like to this:
public async Task DoAJobInTheBackground(string queueName, int someParam)
{
// do other stuff...
// Ensure I'm the only job in this section
using (await _asyncLock.LockAsync())
{
await _aService.CallSomethingAsync());
}
// do other stuff...
}
and from a service called by a controller use my imaginary method IsSomeoneInThereNow():
public void ScheduleAJobUnlessOneIsRunning(string queueName, int someParam)
{
if (!_asyncLock.IsSomeoneInThereNow())
{
_backgroundJobClient.Enqueue<MyJob>(x =>
x.DoAJobInTheBackground(queueName, someParam));
}
}
but so far I can only see how to do this with a separate variable (imagining _isAnybodyInHere is a thread-safe bool or I used Interlocked instead):
public async Task DoAJobInTheBackground(string queueName, int someParam)
{
// do other stuff...
// Ensure I'm the only job in this section
using (await _asyncLock.LockAsync())
{
try
{
_isAnybodyInHere = true;
await _aService.CallSomethingAsync());
}
finally
{
_isAnybodyInHere = false;
}
}
// do other stuff...
}
and from a service called by a controller:
public void ScheduleAJobUnlessOneIsRunning(string queueName, int someParam)
{
if (!_isAnybodyInHere)
{
_backgroundJobClient.Enqueue<MyJob>(x =>
x.DoAJobInTheBackground(queueName, someParam));
}
}
Really it feels like there should be a better way. The AsyncLock doc says:
You can call Lock or LockAsync with an already-cancelled CancellationToken
to attempt to acquire the AsyncLock immediately
without actually entering the wait queue.
but I don't understand how to do that, at least using the synchronous Lock method.
I don't understand how to do that
You can create a new CancellationToken and pass true to create one that is already canceled:
using (_asyncLock.Lock(new CancellationToken(canceled: true)))
{
...
}
The call to Lock will throw if the lock is already held.
That said, I don't think this is a good solution to your problem. There's always the possibility that the background job is just about to finish, the controller checks the lock and determines it's held, and then the background job releases the lock. In that case, the controller will not trigger a background job.
You must never(!) make any assumptions about any other thread or process!
What you must instead do, in this particular example, is to "schedule another job," unless you have already done so. (To avoid "fork bombs.") Then, the job, once it actually begins executing, must decide: "Should I be doing this?" If not, the job quietly exits.
Or – perhaps the actual question here is: "Has somebody else already ≤scheduled_this_job≥?"

c# catch an exception from delegate.begininvoke without calling delegate.endinvoke

I have a program that monitor a DB (or a number of DBs).
for this, I built a class that holds all the information about how to monitor the DB.
the class contains a delegate that points to a function that monitor the DB and changes the state field accordingly.
the main thread create a new instance of the class and calling the class.delegate.begininvoke().
the main thread checks the state of each created class in a loop and inform the user if any changes occur.
a simple example of the code:
Class Monitor
{
private Object lockObj;
private delegate void MonitorHandlerDelegate();
private MonitorHandlerDelegate mainHandler;
private int State;
private int DBid;
public Monitor(int DBid)
{
this.DBid = DBid;
mainHandler += MonitorHandler;
lockObj = new Object();
}
private void MonitorHandler()
{
do
{
state = CheckDB(DBid); // 0 is ok, 1 is fail, 2 is InWork, 3 is stop monitoring
} while (state != 3);
}
public int state
{
get { lock(lockObj) { return State;} }
set { lock(lockObj) {State = value;} }
}
public void Start()
{
this.state = 0;
this.mainHandler.BeginInvoke(null, null);
}
}
public Main()
{
Monitor firstMonitor = new Monitor(20);
firstMonitor.Start();
do
{
if(firstMonitor.state == 1) WriteLine("DB 20 stop working");
} while(true);
}
The problem I encountered is with exception handaling, if the MonitorHandler function throw an exception, i dont have a way to know it.
I dont call the EndInvoke so the exception is not re-throwing to the Main Thread.
My goal is to check the DB status by simply chack the state field of the monitor instance.
If an exception in throwen i need to somehow "transfer" this exception to the Main Thread but i dont want to start checking the state and the Monitor delegate status as well.
I whold love to find a way to the Monitor Thread itself (the one that activated by the .BeginInvoke), to throw the exception in the Main Thread.
Thank you.
I whold love to find a way to the Monitor Thread itself (the one that activated by the .BeginInvoke), to throw the exception in the Main Thread.
Other than something like ThreadAbortException, there is no mechanism to inject an exception into another arbitrary thread.
If you are going to use the delegate's BeginInvoke() method, and you want to catch the exception in a thread different from where the delegate itself is being invoked, then you will need to call EndInvoke() in that thread.
Your other option would be to deal with the exception explicitly and manually. I.e. catch the exception with try/catch in the worker thread, and then use an explicitly defined mechanism of your own choosing (e.g. a ConcurrentQueue<T>) to pass the caught exception to code running in the main thread.
All that said, using a delegate's BeginInvoke() method was never really that ideal a way to execute code asynchronously like that, and today it is even worse of an idea. It's not clear from your question what the nature of the "main thread" is, never mind whether that thread has a synchronization context. But assuming it does (e.g. it's a GUI thread, or an ASP.NET context, etc.) then your desired behavior is easily implemented using Task.Run() to start the asynchronous operation, and then using await in the main thread to capture the completion of that operation, along with any exception that is thrown.
For that matter, even if your main thread does not currently have a synchronization context, it might be the right approach is to give it one. Either by leveraging one of the existing mechanisms, or writing your own. This would be a good idea if, for example, you expect to run into this sort of "propagate the exception from the worker to the main thread" scenario in the code frequently. This would allow you to use the built-in language support for dealing with that (i.e. async/await), rather than having to kludge something for each instance. Implementing the synchronization context isn't trivial, but it's work you can do once, and then reuse over and over.

Why does Parallel.For execute the WinForms message pump, and how to prevent it?

I'm trying to speed up a lengthy (a few ms) operation* using Parallel.For, but I'm getting Paint events all over my WinForms application before the method has returned - suggesting it somehow triggers a message pump. The overall redraw, however, leads to accessing data in an inconsistent state, producing erratic errors and exceptions. I need to assure that Parallel.For, while blocking, doesn't trigger UI code.
My research on this so far has been inconclusive and pointed me roughly to things like synchronization contexts and TaskScheduler implementations, but I have yet to make sense of it all.
If someone could help me along the way by clearing some things up, that would very much be appreciated.
What is the chain of events that leads to Parallel.For triggering WinForms message pump?
Is there any way I can prevent this from happening entirely?
Alternatively, is there any way to tell if a UI event handler is called from the regular message pump, or the "busy" message pump as triggered by Parallel.For?
Edit: * Some context: The above few ms operation is part of a game engine loop, where 16 ms are available for a full update - hence the attribute "lengthy". The context of this problem is executing a game engine core inside its editor, which is a WinForms application. Parallel.For happens during the internal engine update.
This comes from the CLR, it implements the contract that an STA thread (aka UI thread) is never allowed to block on a synchronization object. Like Parallel.For() does. It pumps to ensure that no deadlock can occur.
This gets Paint events to fire, and some others, the exact message filtering is a well-kept secret. It is pretty similar to DoEvents() but the stuff that is likely to cause re-entrancy bugs blocked. Like user input.
But clearly you have a DoEvents() style bug in spades, re-entrancy is forever a nasty bug generator. I suspect you'll need to just set a bool flag to ensure that the Paint event skips an update, simplest workaround. Changing the [STAThread] attribute on the Main() method in Program.cs to [MTAThread] is also a simple fix, but is quite risky if you also have normal UI. Favor the private bool ReadyToPaint; approach, it is simplest to reason through.
You should however investigate exactly why Winforms thinks that Paint is needed, it shouldn't since you are in control over the Invalidate() call in a game loop. It may fire because of user interactions, like min/max/restoring the window but that should be rare. Non-zero odds that there's another bug hidden under the floor mat.
As already explained, Parallel.For itself does not execute the WinForms message pump, but the CLR implementation of Wait which is called by the necessary thread synchronization primitives is causing the behavior.
Luckily that implementation can be overridden by installing a custom SynhronizationContext because all CLR waits actually call Wait method of the current (i.e. associated with the current thread) synchronization context.
The idea is to call WaitForMultipleObjectsEx API which has no such side effects. I can't say whether it is safe or not, CLR designers have their reasons, but from the other side, they have to handle many different scenarios which may not apply to your case, so at least it's worth trying.
Here is the class:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security;
using System.Threading;
using System.Windows.Forms;
class CustomSynchronizationContext : SynchronizationContext
{
public static void Install()
{
var currentContext = Current;
if (currentContext is CustomSynchronizationContext) return;
WindowsFormsSynchronizationContext.AutoInstall = false;
SetSynchronizationContext(new CustomSynchronizationContext(currentContext));
}
public static void Uninstall()
{
var currentContext = Current as CustomSynchronizationContext;
if (currentContext == null) return;
SetSynchronizationContext(currentContext.baseContext);
}
private WindowsFormsSynchronizationContext baseContext;
private CustomSynchronizationContext(SynchronizationContext currentContext)
{
baseContext = currentContext as WindowsFormsSynchronizationContext ?? new WindowsFormsSynchronizationContext();
SetWaitNotificationRequired();
}
public override SynchronizationContext CreateCopy() { return this; }
public override void Post(SendOrPostCallback d, object state) { baseContext.Post(d, state); }
public override void Send(SendOrPostCallback d, object state) { baseContext.Send(d, state); }
public override void OperationStarted() { baseContext.OperationStarted(); }
public override void OperationCompleted() { baseContext.OperationCompleted(); }
public override int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
{
int result = WaitForMultipleObjectsEx(waitHandles.Length, waitHandles, waitAll, millisecondsTimeout, false);
if (result == -1) throw new Win32Exception();
return result;
}
[SuppressUnmanagedCodeSecurity]
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int WaitForMultipleObjectsEx(int nCount, IntPtr[] pHandles, bool bWaitAll, int dwMilliseconds, bool bAlertable);
}
In order to activate it, just add the following line before your Application.Run(...) call:
CustomSynchronizationContext.Install();
Hans explained it in. So what should you do? The easiest path would be to have one volatile bool flag that says if data are consistent and is okay to use them to paint.
Better, but more complicated, solution would be to replace Parallel.For with your own ThreadPool, and send simple task to the pool. Main GUI thread would then stay responsive to user input.
Also, those simple task must not change the GUI directly, but just manipulate the data. Game GUI must be changed only in OnPaint.
Hans explained it. So what should you do? Don't run that loop on the UI thread. Run it on a background thread, for example:
await Task.Run(() => Parallel.For(...));
Blocking on the UI thread is not a good idea in general. Not sure how relevant that is to a game engine loop design but this fixes the reentrancy problems.

How to terminate a thread when the worker can't check the termination string

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...
}
}

Threadsafe properties

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.

Categories

Resources