Simple as this! This is my attempt at one, which requires that functions to be threaded with it use a Pause() function through itself in pausable sections.
using System;
using System.Threading;
class BlackThread {
private bool paused;
private Thread innerThr;
// ---
public bool IsAlive {
get {
return innerThr.IsAlive;
}
}
// ===
public void SetAndGo (ThreadStart start) {
paused = false;
innerThr = new Thread(start);
innerThr.Start();
WaitForIt();
}
// ---
public void Pause() {
paused = true;
while (paused);
}
public void Unpause() {
paused = false;
}
public void WaitForIt() {
while(!paused && IsAlive);
}
public void Continue() {
Unpause();
WaitForIt();
}
}
class MainClass {
static void pausableFunction (BlackThread self) {
Console.WriteLine("* Waiting...");
self.Pause();
Console.WriteLine("* Doing stuff.");
self.Pause();
Console.WriteLine("* Finished!");
}
static void Main() {
BlackThread noir = new BlackThread();
noir.SetAndGo(() => pausableFunction(noir));
while (noir.IsAlive) {
Console.Write("> ");
Console.ReadKey();
noir.Continue();
}
}
}
Sadly, it’s not one that can be paused at any time, but a thread for functions that require to wait for outside processing to be able to continue. Like an action by a game mob that requires its frame to be drawn by the draw loop before it can continue, and the mob’s A.I.’s is processed in the game’s main loop.
I guess it’d make it some kind of pseudo-thread? Anyway.
It would allow the mob to process this action bit by bit every loop, instead of cascading checkings in its A.I. like…
if mob is doing action {
if mob has already done this previous part of the action {
do the following part
}
}
…it’d rather be like this, in a thread:
do the first step of the action
Wait for it to be rendered...
do the following step of the action
Wait for it to be rendered...
do the last step of the action
(Action ends here, no need to wait for anything anymore)
Now, my implementation has a bug which I cannot figure out how to fix. When it’s supposed to unpause the BlackThread, it remains paused in the function (in this case, pausableFunction()) that uses it. I guess it’s because of how the instance is passed?
If it’s what I’m guessing – that is, something (and I’d guess it’s bool paused) is passed by value instead of reference – how could I fix it?
I’m really used to the pointers of C and C++, so sometimes I get a bit tangled when dealing in C# with the communication of an object’s values between scopes.
This here is a version of the code the works, a prototype to say:
using System;
using System.Threading;
class Program {
static bool paused;
static void Pause() {
paused = true;
while (paused);
}
static void Unpause() {
paused = false;
}
static void WaitForIt(Thread waited) {
while(!paused && waited.IsAlive);
}
static void Continue (Thread ToStop) {
Unpause();
WaitForIt(ToStop);
}
static void SetAndGo (out Thread thread, ThreadStart Start) {
thread = new Thread(Start);
thread.Start();
WaitForIt(thread);
}
// ---
static void thr (string chant) {
// Console.WriteLine("Waiting...");
// Pause();
// Console.WriteLine("{0}", chant);
// Pause();
// Console.WriteLine("Well, I'm finished!");
Console.WriteLine("I'm finished!");
}
static void Main() {
// Thread tt = new Thread(() => thr());
// tt.Start();
// WaitForIt(tt);
Thread tt;
SetAndGo(out tt, (() => thr("I'm doing stuff.")));
while (tt.IsAlive) {
Console.Write("> ");
Console.ReadKey();
Continue(tt);
}
}
}
I’m only not using it because I’d rather have everything in charge of a specific class for the matter, something that would also enhance readability.
Alright, I’ve accomplished what I was trying already, so I’ll leave my code here for future reference!
This is the BlackThread class in the end:
And here, an example of its use:
What I’ve opted to use in the end were two AutoResetEvent handlers. One is managed in the function of the thread that requires pausing, and that pauses the main loop, the waiter ARE, and another, the pauser ARE, managed in the main loop, and that pauses the thread with the function with support for BlackThread; that is, has acess to a BlackThread instance.
In this case I’ve used a static BlackThread object, but it can also be passed as a parameter to the function.
And yes, it’s named after the Buddhist hell!