Threaded function does not behave as I expect it to - c#

This is (roughly) what I have:
class A
{
public bool IsInUpdate = false;
public void Update()
{
IsInUpdate = true;
//(...do stuff...)
IsInUpdate = false;
}
}
class B
{
A a_inst;
System.Threading.Thread physicsThread = null;
void Draw()
{
physicsThread = new System.Threading.Thread(a_inst.Update);
physicsThread.Start();
}
void Update()
{
while(physicsThread.IsAlive)
{
// Right here there can be cases where physicsThread.IsAlive is true but IsInUpdate is false, how does that happen?
}
(...do stuff...)
}
}
Question is in the comments of the code. Basically the physics thread instance says it's alive but the function it's calling has clearly been finished calling (as can be seen by the bool being set to false).
Any ideas why this happens? All I want to do is make sure the update function in class B does not execute until the threaded update function of class A has executed...

Since IsInUpdate is simply a public field (and non-volatile at that), there are no guarantees about what you see; the normal sensible rules about what you see only apply on a single thread, and you have not guarded any of this data. There is also an edge-case around the start condition, but personally I would be using either lock (if you need to wait for it to complete), or maybe Interlocked if you just need to know if it is active.
For example:
class A
{
private readonly object syncLock = new object();
public object SyncLock { get { return syncLock; } }
public void Update()
{
lock(SyncLock)
{
//(...do stuff...)
}
}
}
and
void Update()
{
lock(a_inst.SyncLock)
{
(...do stuff...)
}
}
With the above, you are guaranteed that only one thread will have the lock at any time, so if you get to "do stuff" you know that it isn't also running the other Update(). If you need to wait etc there are also Wait() / Pulse() methods against locks, or you can use gates such as ManualResetEvent/AutoResetEvent.
Things like lock also ensure correct memory barriers between the threads, so you see the correct data.

This situation can happen when the Update function has not been called yet. Just because you have called Start on the thread doesn't mean it's immediately going to execute it's main function. I'm not 100% sure if there is a slight window of opportunity where the thread is still alive but the main function has finished executing.
Basically you want to have a look at ManualResetEvent or AutoResetEvent to signal that your thread has finished working. Alternatively an event you can raise after Update() has finished and B can subscribe to might be good enough. Like this:
class A
{
public event EventHandler UpdateFinished;
public void Update()
{
... do work
var handler = UpdateFinished;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
class B
{
public void Draw()
{
a_inst.UpdateFinished += HandleUpdateFinished;
... start your thread
}
private void HandleUpdateFinished(object sender, EventArgs e)
{
... do whatever
}
}

Related

Avoid starting new thread with lock

Is this possible to lock method for one thread and force another to go futher rather than waiting until first thread finish? Can this problem be resolved with static thread or some proper pattern with one instance of mendtioned below service.
For presentation purposes, it can be done with static boolen like below.
public class SomeService
{
private readonly IRepository _repo;
public SomeService(IRepository repo)
{
_repo = repo;
}
private Thread threadOne;
public static bool isLocked { get; set; }
public void StartSomeMethod()
{
if(!isLocked)
{
threadOne = new Thread(SomeMethod);
isLocked = true;
}
}
public void SomeMethod()
{
while(true)
{
lots of time
}
...
isLocked = false;
}
}
I want to avoid situation when user clicked, by accident, two times to start and accidentailly second thread starts immediatelly after first finished.
You can use lock :)
object locker = new object();
void MethodToLockForAThread()
{
lock(locker)
{
//put method body here
}
}
Now the result will be that when this method is called by a thread (any thread) it puts something like flag at the beginning of lock: "STOP! You are not allowed to go any further, you must wait!" Like red light on crossroads.
When thread that called this method first, levaes the scope, then at the beginning of the scope this "red light" changes into green.
If you want to not call the method when it is already called by another thread, the only way to do this is by using bool value. For example:
object locker = new object();
bool canAccess = true;
void MethodToLockForAThread()
{
if(!canAccess)
return;
lock(locker)
{
if(!canAccess)
return;
canAccess = false;
//put method body here
canAccess = true;
}
}
Other check of canAccess in lock scope is because of what has been told on comments. No it's really thread safe. This is kind of protection that is advisible in thread safe singleton.
EDIT
After some discussion with mjwills I have to change my mind and turn more into Monitor.TryEnter. You can use it like that:
object locker = new object();
void ThreadMethod()
{
if(Monitor.TryEnter(locker, TimeSpan.FromMiliseconds(1))
{
try
{
//do the thread code
}
finally
{
Monitor.Exit(locker);
}
} else
return; //means that the lock has not been aquired
}
Now, lock could not be aquired because of some exception or because some other thread has already acuired it. In second parameter you can pass the time that a thread will wait to acquire a lock. I gave here short time because you don't want the other thread to do the job, when first is doing it.
So this solution seems the best.
When the other thread could not acquire the lock, it will go further instead of waiting (well it will wait for 1 milisecond).
Since lock is a language-specific wrapper around Monitor class, you need Monitor.TryEnter:
public class SomeService
{
private readonly object lockObject = new object();
public void StartSomeMethod()
{
if (Monitor.TryEnter(lockObject))
{
// start new thread
}
}
public void SomeMethod()
{
try
{
// ...
}
finally
{
Monitor.Exit(lockObject);
}
}
}
You can use a AutoResetEvent instead of your isLocked flag.
AutoResetEvent autoResetEvent = new AutoResetEvent(true);
public void StartSomeMethod()
{
if(autoResetEvent.WaitOne(0))
{
//start thread
}
}
public void SomeMethod()
{
try
{
//Do your work
}
finally
{
autoResetEvent.Set();
}
}

How to abort a thread properly? [duplicate]

This question already has answers here:
How to terminate a thread in C#?
(4 answers)
Closed 5 years ago.
I'm writing a scripting interface for a server emulator for NPC chats. The player can initiate a NPC chat by clicking on the NPC. The NPC can send text dialogs. Those text dialogs also contain a End Chat button to end the chat before the script finishes execution, or the player can continue with the text dialogs normally until they end.
When the player interrupts the chat, a special packet is sent.
I've created a class called WaitableResult which takes advantage of ManualResetEvent to block the current thread until given result and then returns the result:
public sealed class WaitableResult<T> where T : struct
{
public T Value { get; private set; }
private ManualResetEvent mEvent;
public WaitableResult()
{
mEvent = new ManualResetEvent(false);
}
public void Wait()
{
mEvent.WaitOne();
}
public void Set(T value)
{
mEvent.Set();
this.Value = value;
}
}
This is my script classes:
internal sealed class NpcScript : ScriptBase
{
public WaitableResult<bool> BoolResult { get; private set; }
private Npc mNpc;
private Player mPlayer;
public NpcScript(Npc npc, Player player)
: base(string.Format(#"..\..\scripts\npcs\{0}.lua", npc.Script), true)
{
mNpc = npc;
mPlayer = player;
mPlayer.NpcConversation = this;
this.Expose("answer_no", false);
this.Expose("answer_yes", true);
this.Expose("answer_decline", false);
this.Expose("answer_accept", true);
this.Expose("say", new Func<string, bool>(this.Say));
this.Expose("askYesNo", new Func<string, bool>(this.AskYesNo));
}
public override void Dispose()
{
base.Dispose();
mPlayer.NpcConversation = null;
}
private bool Say(string text)
{
this.BoolResult = new WaitableResult<bool>();
using (OutPacket outPacket = mNpc.GetDialogPacket(ENpcDialogType.Standard, text, 0, 0))
{
mPlayer.Client.SendPacket(outPacket);
}
this.BoolResult.Wait();
return this.BoolResult.Value;
}
private bool AskYesNo(string text)
{
this.BoolResult = new WaitableResult<bool>();
using (OutPacket outPacket = mNpc.GetDialogPacket(ENpcDialogType.YesNo, text))
{
mPlayer.Client.SendPacket(outPacket);
}
this.BoolResult.Wait();
return this.BoolResult.Value;
}
}
public abstract class ScriptBase
{
private string mPath;
private Thread mThread;
private MoonSharp.Interpreter.Script mScript;
public ScriptBase(string path, bool useThread = false, CoreModules modules = CoreModules.None)
{
mPath = path;
if (useThread) mThread = new Thread(new ThreadStart(() => mScript.DoFile(mPath)));
mScript = new MoonSharp.Interpreter.Script(modules);
}
public void Execute()
{
if (mThread != null)
{
mThread.Start();
}
else
{
mScript.DoFile(mPath);
}
}
public virtual void Dispose()
{
if (mThread != null)
{
mThread.Abort();
mThread = null;
}
}
protected void Expose(string key, object value)
{
mScript.Globals[key] = value;
}
}
And here's an example of a script:
say('test')
say('some more stuff')
say('good bye')
When a player initiates a chat with a NPC and finishes it without interrupting it (aka closing it using the End Chat button), the thread should be aborted by itself (as it finished all it's instructions).
However, when a player aborts the chat before it finishes execution, I'm calling the Dispose button to manually abort the thread - but I'm not sure it's the right way to do it.
My memory usage also increases by 1 MB everytime a player starts a chat, so that's also kind of weird.
As Quantic has already addressed, aborting a thread by means of Thread.Abort invites unexpected - even dangerous results. Quantic also addressed the preferred pattern to deal with a thread, usually the thread loops and checks for a termination flag, which is not possible if you are executing an arbitrary Lua script.
One option you have is to create a minimalistic debugger and attach it to your script. Once this debugger is attached, the IDebugger.GetAction() method will be called for every instruction in the running script. If during the GetAction()call you raise an Exception, the script will be terminated, cleanly, by the debugger.
Here is an example of a sentinel, minimalistic debugger that stops a long-running script using such a technique. As you can see, most of the implementation is empty. In your case, instead of using a running instruction counter, you may simply have a boolean flag that indicates that the script must be terminated.
public DebuggerAction GetAction(int ip, SourceRef sourceref)
{
if( _abortScript )
throw new MyException(); // abort cleanly
// Proceed running the next statement
return new DebuggerAction() {
Action = DebuggerAction.ActionType.StepIn,
};
}
Regarding the memory increase you are experiencing, that is one of the inconveniences of manually spawning threads, each thread initializes its own stack space and on a 32-bit process, the default is precisely 1MB. There is a Thread constructor overload that allows you to customize the stack size; Depending on the complexity of the scripts, this value could probably be set to a smaller value without risking a stack overflow condition. Another option to minimize memory usage would be to use a Task.Run instead of spawning your own thread (this makes use of the Thread pool), but then refraining from using Thread.Abort would be mandatory, you don't want to go killing pooled threads!

Multiple calls (at once) to a method that can only run one at a time

I have a business logic method that has to be finished before it can be called again. Multiple clients have the ability to call it at once:
public void DoSomething() {}
I was thinking about solving it by making the method private, and creating a new public method to put the requests on a queue:
public void QueueSomeWork()
{
// put on a Queue object
// How will DoSomething get invoked now?
}
private void DoSomething() {}
I'm trying to solve this issue in an elegant way. My issue is how DoSomething() will know to run. I thought about creating a timer to check the queue, but then it would be running 24/7 for something that happens maybe twice per year.
Another thought is to have DoSomething() fire an event when it's done that something else would subscribe to, pick some work off the queue, and call DoSomething(). Is there a better way?
Why don't you use a lock guard?
Eg :
private static Object lockGuard = new Object();
public void DoSomething()
{
lock (lockGuard)
{
//logic gere
}
}
Locking a resource will prevent access from multiple threads in the same time.
More on lock : http://msdn.microsoft.com/en-us/library/c5kehkcz(v=vs.110).aspx
If the numbers are not so high (it depends how DoSomething internals consume resource); I would go with this:
public static async void QueueSomeWork()
{
await Task.Run(() => { DoSomething(); });
}
static readonly object lockObject = new object();
static void DoSomething()
{
lock (lockObject)
{
// implementation
}
}
And if the numbers are higher, you should put a limit on number of allowed queued tasks:
static long numberOfQueuedTasks = 0;
const long MAX_TASKS = 10000; // it depends how DoSomething internals consume resource
public static async void QueueSomeWork()
{
if (numberOfQueuedTasks > MAX_TASKS)
{
var wait = new SpinWait();
while (numberOfQueuedTasks > MAX_TASKS) wait.SpinOnce();
}
await Task.Run(() => { Interlocked.Increment(ref numberOfQueuedTasks); DoSomething(); });
}
static readonly object lockObject = new object();
static void DoSomething()
{
try
{
lock (lockObject)
{
// implementation
}
}
finally
{
Interlocked.Decrement(ref numberOfQueuedTasks);
}
}
Simple way of doing it is by decorating the method with MethodImplOptions.Synchronized, whose function is similar to the synchronized keyword in Java:
[MethodImpl(MethodImplOptions.Synchronized)]
private void DoSomething()
{
// ...
}
The main downside is that this will lock on the current instance, which might lead to deadlock if you're already using locking elsewhere.
Here is an idea. You'd probably want to lock the doSomethingCount when using it, but as for queuing the DoSomething and going on this might work because it runs on a separate thread. Since you were ok with a queue, I assume you want fire and forget and don't actually need to block the caller.
// This will increment the count and kick off the process of going through
// the calls if it isn't already running. When it is done, it nulls out the task again
// to be recreated when something is queued again.
public static void QueueSomething()
{
doSomethingCount++;
if (doSomethingTask == null)
{
doSomethingTask =
Task.Run((Action)(() =>
{
while (doSomethingCount > 0)
{
DoSomething();
doSomethingCount--;
}
}))
.ContinueWith(t => doSomethingTask = null);
}
}
// I just put something in here that would take time and have a measurable result.
private static void DoSomething()
{
Thread.Sleep(50);
thingsDone++;
}
// These two guys are the data members needed.
private static int doSomethingCount = 0;
private static Task doSomethingTask;
// This code is just to prove that it works the way I expected. You can use it too.
public static void Run()
{
for (int i = 0; i < 10; i++)
{
QueueSomething();
}
while (thingsDone < 10)
{
Thread.Sleep(100);
}
thingsDone = 0;
QueueSomething();
while (thingsDone < 1)
{
Thread.Sleep(100);
}
Console.WriteLine("Done");
}
// This data point is just so I could test it. Leaving it in so you can prove it yourself.
private static int thingsDone = 0;
if this is code-only issue, the lock solution is good. But sometimes you run a DB transaction, where series of objects (records) have to be modified with no interference. Good example is when you re-run sequence enumeration of DB records. You can create a lock table in DB and lock a specific defined record in it for update first thing in the transaction. This will prevent other transactions created by your application (in the same code area) to even get to the table you updating. And second call will only proceed after the first one is done. Just a tip.

Is the System.Timers.Timer.Enabled property thread safe and so can it be accessed from the timer's Elapsed event?

I have an Elapsed method in which I have a while loop. If the timer is disabled/stopped from another thread, I would like this loop to stop. Can I rely on the timer's Enabled property in the Elapsed method for this or should I create a "volatile bool timerEnabled" variable just to be sure. My testings show that it's OK, but I'd like to be sure of this before putting it in production.
This is what I'm trying to achieve (not actual code but close)
private volatile bool isElapsedAlreadyRunning
void myTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (!isElapsedAlreadyRunning) // to prevent reentrance
{
isElapsedAlreadyRunning = true;
try
{
while (myTimer.Enabled && some other condition)
{
do stuff
}
}
finally
{
isElapsedAlreadyRunning = false;
}
}
}
myTimer.Start() and myTimer.Stop() are in other methods that can be called frrom other threads
I'm using the System.Timers.Timer class
If you have any other comment or see any pitfall in this design feel free to comment :)
Thanks
Edit :
Man, threading is hard. Based on the answers and other stackoverflow questions (this answer particularly) this would be the way to do it (I hope this time it's OK)
public class NoLockTimer : IDisposable
{
private readonly System.Timers.Timer _timer;
private bool _isTimerStopped = false;
private readonly object _isTimerStoppedLock = new object();
public NoLockTimer()
{
_timer = new System.Timers.Timer { AutoReset = false, Interval = 1000 };
_timer.Elapsed += delegate
{
try
{
while (!IsTimerStopped && some other condition)
{
// do stuff
}
}
catch (Exception e)
{
// Do some logging
}
finally
{
if (!IsTimerStopped)
{
_timer.Start(); // <- Manual restart.
}
}
};
_timer.Start();
}
public void Stop()
{
IsTimerStopped = true;
if (_timer != null)
{
_timer.Stop();
}
}
private bool IsTimerStopped
{
get
{
lock (_isTimerStoppedLock)
{
return _isTimerStopped;
}
}
set
{
lock (_isTimerStoppedLock)
{
_isTimerStopped = value;
}
}
}
public void Dispose()
{
Stop();
if (_timer != null)
{
_timer.Dispose();
}
}
}
No, this is not safe. The Elapsed event handler is called on a threadpool thread. You cannot predict when that thread actually calls your method, it depends on what other TP threads are running in the process. Having two calls in flight at the same time is technically possible. Which makes the volatile keyword on the isElapsedAlreadyRunning variable not nearly good enough to ensure that the method is thread-safe, you must use the lock keyword or Monitor.TryEnter() instead.
This problem disappears when you set the Timer's AutoReset property to false. Be sure to restart the timer in a finally block, another nasty problem with the Timer.Elapsed event is that exceptions get swallowed without diagnostic. System.Threading.Timer is an all-around better timer with fewer surprises like this.
The Timer.Enabled property has a similar problem, you'll always see it late.
Your guard with isElapsedAlreadyRunning is obviously not thread-safe.
But you can simply replace it with a lock(...) { ...} statement.

Thread.Interrupt to stop long sleep at app shutdown - Is there a better approach

I'm having a small background thread which runs for the applications lifetime - however when the application is shutdown, the thread should exit gracefully.
The problem is that the thread runs some code at an interval of 15 minutes - which means it sleeps ALOT.
Now in order to get it out of sleep, I toss an interrupt at it - my question is however, if there's a better approach to this, since interrupts generate ThreadInterruptedException.
Here's the gist of my code (somewhat pseudo):
public class BackgroundUpdater : IDisposable
{
private Thread myThread;
private const int intervalTime = 900000; // 15 minutes
public void Dispose()
{
myThread.Interrupt();
}
public void Start()
{
myThread = new Thread(ThreadedWork);
myThread.IsBackground = true; // To ensure against app waiting for thread to exit
myThread.Priority = ThreadPriority.BelowNormal;
myThread.Start();
}
private void ThreadedWork()
{
try
{
while (true)
{
Thread.Sleep(900000); // 15 minutes
DoWork();
}
}
catch (ThreadInterruptedException)
{
}
}
}
There's absolutely a better way - either use Monitor.Wait/Pulse instead of Sleep/Interrupt, or use an Auto/ManualResetEvent. (You'd probably want a ManualResetEvent in this case.)
Personally I'm a Wait/Pulse fan, probably due to it being like Java's wait()/notify() mechanism. However, there are definitely times where reset events are more useful.
Your code would look something like this:
private readonly object padlock = new object();
private volatile bool stopping = false;
public void Stop() // Could make this Dispose if you want
{
stopping = true;
lock (padlock)
{
Monitor.Pulse(padlock);
}
}
private void ThreadedWork()
{
while (!stopping)
{
DoWork();
lock (padlock)
{
Monitor.Wait(padlock, TimeSpan.FromMinutes(15));
}
}
}
For more details, see my threading tutorial, in particular the pages on deadlocks, waiting and pulsing, the page on wait handles. Joe Albahari also has a tutorial which covers the same topics and compares them.
I haven't looked in detail yet, but I wouldn't be surprised if Parallel Extensions also had some functionality to make this easier.
You could use an Event to Check if the Process should end like this:
var eventX = new AutoResetEvent(false);
while (true)
{
if(eventX.WaitOne(900000, false))
{
break;
}
DoWork();
}
There is CancellationTokenSource class in .NET 4 and later which simplifies this task a bit.
private readonly CancellationTokenSource cancellationTokenSource =
new CancellationTokenSource();
private void Run()
{
while (!cancellationTokenSource.IsCancellationRequested)
{
DoWork();
cancellationTokenSource.Token.WaitHandle.WaitOne(
TimeSpan.FromMinutes(15));
}
}
public void Stop()
{
cancellationTokenSource.Cancel();
}
Don't forget that CancellationTokenSource is disposable, so make sure you dispose it properly.
One method might be to add a cancel event or delegate that the thread will subscribe to. When the cancel event is invoke, the thread can stop itself.
I absolutely like Jon Skeets answer. However, this might be a bit easier to understand and should also work:
public class BackgroundTask : IDisposable
{
private readonly CancellationTokenSource cancellationTokenSource;
private bool stop;
public BackgroundTask()
{
this.cancellationTokenSource = new CancellationTokenSource();
this.stop = false;
}
public void Stop()
{
this.stop = true;
this.cancellationTokenSource.Cancel();
}
public void Dispose()
{
this.cancellationTokenSource.Dispose();
}
private void ThreadedWork(object state)
{
using (var syncHandle = new ManualResetEventSlim())
{
while (!this.stop)
{
syncHandle.Wait(TimeSpan.FromMinutes(15), this.cancellationTokenSource.Token);
if (!this.cancellationTokenSource.IsCancellationRequested)
{
// DoWork();
}
}
}
}
}
Or, including waiting for the background task to actually have stopped (in this case, Dispose must be invoked by other thread than the one the background thread is running on, and of course this is not perfect code, it requires the worker thread to actually have started):
using System;
using System.Threading;
public class BackgroundTask : IDisposable
{
private readonly ManualResetEventSlim threadedWorkEndSyncHandle;
private readonly CancellationTokenSource cancellationTokenSource;
private bool stop;
public BackgroundTask()
{
this.threadedWorkEndSyncHandle = new ManualResetEventSlim();
this.cancellationTokenSource = new CancellationTokenSource();
this.stop = false;
}
public void Dispose()
{
this.stop = true;
this.cancellationTokenSource.Cancel();
this.threadedWorkEndSyncHandle.Wait();
this.cancellationTokenSource.Dispose();
this.threadedWorkEndSyncHandle.Dispose();
}
private void ThreadedWork(object state)
{
try
{
using (var syncHandle = new ManualResetEventSlim())
{
while (!this.stop)
{
syncHandle.Wait(TimeSpan.FromMinutes(15), this.cancellationTokenSource.Token);
if (!this.cancellationTokenSource.IsCancellationRequested)
{
// DoWork();
}
}
}
}
finally
{
this.threadedWorkEndSyncHandle.Set();
}
}
}
If you see any flaws and disadvantages over Jon Skeets solution i'd like to hear them as i always enjoy learning ;-)
I guess this is slower and uses more memory and should thus not be used in a large scale and short timeframe. Any other?

Categories