Consider the following abstract class:
public abstract class Worker {
protected bool shutdown;
protected Thread t;
/// <summary>
/// defines that we have an auto unpause scheduled
/// </summary>
private bool _unpauseScheduled;
/// <summary>
/// when paused; schedule an automatic unpause when we
/// reach this datetime
/// </summary>
private DateTime pauseUntil;
private bool _isStopped = true;
public bool IsStopped {
get {
return t.ThreadState == ThreadState.Stopped;
}
}
private bool _isPaused = false;
public bool IsPaused {
get {
return _isPaused;
}
}
private string stringRepresentation;
public Worker() {
t = new Thread(ThreadFunction);
stringRepresentation = "Thread id:" + t.ManagedThreadId;
t.Name = stringRepresentation;
}
public Worker(string name) {
t = new Thread(ThreadFunction);
stringRepresentation = name;
t.Name = stringRepresentation;
}
public void Start() {
OnBeforeThreadStart();
t.Start();
}
public void ScheduleStop() {
shutdown = true;
}
public void SchedulePause() {
OnPauseRequest();
_isPaused = true;
}
public void SchedulePause(int seconds) {
_unpauseScheduled = true;
pauseUntil = DateTime.Now.AddSeconds(seconds);
SchedulePause();
}
public void Unpause() {
_isPaused = false;
_unpauseScheduled = false;
}
public void ForceStop() {
t.Abort();
}
/// <summary>
/// The main thread loop.
/// </summary>
private void ThreadFunction() {
OnThreadStart();
while (!shutdown) {
OnBeforeLoop();
if (!IsPaused) {
if (!OnLoop()) {
break;
}
} else {
// check for auto-unpause;
if (_unpauseScheduled && pauseUntil < DateTime.Now) {
Unpause();
}
}
OnAfterLoop();
Thread.Sleep(1000);
}
OnShutdown();
}
public abstract void OnBeforeThreadStart();
public abstract void OnThreadStart();
public abstract void OnBeforeLoop();
public abstract bool OnLoop();
public abstract void OnAfterLoop();
public abstract void OnShutdown();
public abstract void OnPauseRequest();
public override string ToString() {
return stringRepresentation;
}
}
I use this class to create Threads that are designed to run for the lifetime of the application, but also with the ability to pause and stop the threads as needed.
I can't help but shake the feeling that my implementation is naive though. My use of Thread.Sleep() gives me pause. I am still learning the ins and outs of threads, and I am looking to see what others might do instead.
The Worker derived objects need to be able to do the following:
Run for the lifetime of the application (or as long as needed)
Be able to stop safely (finish what is was doing in OnLoop())
Be able to stop unsafely (disregard what is happening in OnLoop())
Be able to pause execution for a certain amount of time (or indefinitly)
Now, my implementation works, but that is not good enough for me. I want to use good practice, and I could use some review of this to help me with that.
I can't help but shake the feeling that my implementation is naive though. My use of Thread.Sleep() gives me pause. I am still learning the ins and outs of threads, and I am looking to see what others might do instead.
Your intuitions are good here; this is a naive approach, and any time you sleep a thread in production code you should think hard about whether you're making a mistake. You're paying for that worker; why are you paying for it to sleep?
The right way to put a thread to sleep until it is needed is not to sleep and poll in a loop. Use an appropriate wait handle instead; that's what wait handles are for.
But a better approach still would be to put an idle thread back into a pool of threads; if the work needs to be started up again in the future, schedule it onto a new worker thread. A thread that can sleep forever is a huge waste of resources; remember, a thread is a million bytes of memory by default. Would you allocate a bunch of million-byte arrays and then never use them?
You should study the design of the Task Parallel Library for additional inspiration. The insight of the TPL is that threads are workers, but what you care about is getting tasks completed. Your approach puts a thin layer on top of threads, but it does not get past the fact that threads are workers; managing workers is a pain. State your tasks, and let the TPL assign them to workers.
You might also examine the assumptions around the up-to-date-ness of your various flags. They have no locks and are not volatile, and therefore reads and writes can be moved forwards and backwards in time basically at the whim of the CPU.
You also have some non-threading bugs to think about. For example, suppose you decide to pause for thirty minutes, but at five minutes before clocks "spring forward" for daylight savings time. Do you pause for half an hour, or five minutes? Which do you actually intend?
I am working on some interesting concepts related to wrapping threads.
I have called it Fiber for now.
http://net7mma.codeplex.com/SourceControl/latest#Concepts/Classes/Threading/Threading.cs
Eric Lippert is is correct about paying a worker to sleep in some regard, if you imagine Eric Lippert is paid salary as opposed to via the hour then technically he is paid to sleep just as any other salaried employee.
How this relates to the concept at hand?
What about Priority? The CPU(s) that are executing your code are contending with their own pipelines for execution context as well as requests from the scheduler.
No one makes any mention of reducing the Priority which will reduce the amount of time given to execution of the context by the scheduler.
Chaining the Priority will thus increase the amount of cycles given to other context's and additionally will reduce the power consumption of your processor at the same time making your application run longer if it has a limited source of power (unless of course your using the excess heat to provide additional power to your system.)
Related
I'm writing a simplified asynchronous event driven Timer class. Just wondering if this will work under all conditions and if it's thread safe. IE, any chance of it failing during invoke or reading the Enabled property or setting the AutoReset feature.
namespace Sandbox
{
public class AsyncTimer
{
public volatile bool AutoReset = true;
volatile bool enabled = false;
public volatile int Interval;
CancellationTokenSource? cts;
public volatile Action? Elapsed;
public bool Enabled { get { return enabled; } }
public AsyncTimer (int interval) => Interval = interval;
public void Start(bool startElapsed = false)
{
if (startElapsed) Elapsed?.Invoke();
enabled = true;
cts = new();
_ = Task.Run(() => RunTimerAsync());
}
public void Stop()
{
enabled = false;
cts?.Cancel();
}
async void RunTimerAsync()
{
while (enabled && !cts!.IsCancellationRequested)
{
await Task.Delay(Interval);
Elapsed?.Invoke();
if (!AutoReset) cts.Cancel();
}
}
}
}
As far as I can see, this is just a wrapper around Threading.Timer with a bunch of extra stuff around it that does not add any actual functionality. Your timer works by calling Task.Delay, but this is just a wrapper around Threading.Timer, so you might as well cut out the middleman.
Most the functionality you expose is already provided by this timer by calling the .Change method. If you want to provide a more intuitive interface I would suggest wrapping this timer, or provide some extension methods, instead.
If you want the behavior that guarantees that the event is not raised concurrently, and that the execution-time is added to the period time, you should wrap the timer and set some due-time and an infinite period. Then at the end of your event handler you would call .Change again to restart the timer.
If you write a simple wrapper around Threading.Timer you will have a much easier time ensuring thread safety, since the Threading.Timer is thread safe.
As it is, I think your class is probably kind of thread safe. But I'm fairly sure it can cause some behavior that is unexpected. For example, calling .Start() multiple times would cause multiple loops to be started. I would have expected such a method to be idempotent.
My unity project is a procedural environment on Android and creates terrains and stuff at runtime. The overall workflow I use is to calculate anything non-unity in a worker thread and when the data is calculated, I call Unity API within the main thread.
The problem is that sometimes (like every 200 frames) the worker thread affects the main thread's performance. That could show itself with a nasty spike in rendering time.
So what to do with multithreading in unity?
EDIT: The android device is quad core.
EDIT 2: I believe what Sam said in the comments is exactly what's happening.
I wonder if you can determine what core the code is running on, or if
you can set the thread affinity? I found some links where people
described similar situations: here and here. Sounds like
it's picking the same core as the main thread occasionally.
So maybe this is not about unity but every real time interactive multithreaded application. I believe it is possible to set thread affinity on some versions of some platforms but that destroys the cross platform status of the system.
PS: Not exactly the main issue but to make the question more concrete, I will include the worker thread implementation. It is a modified version of the worker thread implementation suggested in this post. The modified version is like this:
public static class JobScheduler
{
private static Queue<Job> Jobs = new Queue<Job>();
private static volatile bool isBusy;
private static ManualResetEvent _workAvailable = new ManualResetEvent(false);
static JobScheduler()
{
var backgroundWorkThread = new Thread(BackgroundThread)
{
IsBackground = true,
Priority = ThreadPriority.Lowest,
Name = "BasicBackgroundWorker Thread"
};
backgroundWorkThread.Start();
}
private static void BackgroundThread()
{
int jobCnt;
while (true)
{
Job? workItem=null;
lock (Jobs)
{
jobCnt = Jobs.Count;
if (jobCnt != 0 && !isBusy)
{
workItem = Jobs.Dequeue();
}
}
if (workItem!=null)
{
isBusy = true;
workItem.Value.callback(workItem.Value.param);
}
else
{
_workAvailable.WaitOne();
_workAvailable.Reset();
}
}
}
public static void AddJob(Job Job)
{
lock (Jobs)
{
Jobs.Enqueue(Job);
}
_workAvailable.Set();
}
public static void JobDone()
{
isBusy = false;
_workAvailable.Set();
}
}
And the Job struct:
public struct Job
{
public object param;
public WaitCallback callback;
public Job(WaitCallback callBackP
, object parameter)
{
callback = callBackP;
param = parameter;
}
}
Whenever needed I call JobScheduler.AddJob to enqueue a job and call JobScheduler.JobDone after the job is done to allow the next job to run.
Also the ThreadPool is not an option since it produces unnecessary garbage and is not very flexible to use.
I have class which implements an endless worker thread like this example, in my case representing a body. During runtime I will have between 0 and ~8 instances live at any time with instances constantly being created and destroyed.
Most of the time this class has a lifecycle of 30 seconds to 5 minutes but occasionally there may be a number of instances created and destroyed in a relatively short period of time. This is where I tend to run into performance issues given the low spec hardware this code is running on.
I would now like to rewrite the behavior so that I use a ThreadPool for my collection of running workers and I am struggling to find the correct way to structure the code.
Basically the code I have at the moment is something like
public class BodyCollection : IReadOnlyDictionary<ulong, TrackedBody>
{
public void Update()
{
if (createNew)
{
var body = new TrackedBody();
body.BeginTracking();
this.Add(1234, body);
}
if (remove)
{
TrackedBody body = this[1234];
body.StopTracking();
this.Remove(body);
}
}
}
public class TrackedBody
{
private readonly Thread _BiometricsThread;
private volatile bool _Continue = true;
public TrackedBody()
{
_BiometricsThread = new Thread(RunBiometricsThread);
}
public void BeginTracking()
{
_BiometricsThread.Start();
}
public void StopTracking()
{
_Continue = false;
}
private void RunBiometricsThread()
{
while(_Continue)
{
System.Threading.Thread.Sleep(1000);
}
}
}
So how do I re-write the above to utilize a ThreadPool correctly and so that I can cancel running threads on the ThreadPool as required? Do I use CancellationTokens or ManualResetEvents to control the threads?
I strongly believe you should be using more modern methods of asynchronous programming. We are going to use the Task Parallel Library here because it gives you the features you want for free:
Tracking completion
Cancellation
Thread pool
public class TrackedBody
{
public Task BeginTrackingAsync(CancellationToken cancellation)
{
return Task.Run(() => RunBiometricsThread(cancellation));
}
private void RunBiometricsThread(CancellationToken cancellation)
{
while(!cancellation.IsCancellationRequested)
{
Task.Delay(1000, cancellation);
}
}
}
Note that I have removed the async keyword. This was doing nothing on its own.
You can use the task to track the state of the ongoing work. You can use the cancellation token to stop all work.
I have a single thread VB.net service that checks a database for specific information. If the info does not exist, it needs to wait 15 minutes and try again. What is the best method to have the service wait during this 15 minute period? I considered a Do loop with threading.thread.sleep, but am always reading how that is bad to use, but I do not know an alternative. Any suggestions of a better method for this would be appreciated.
I guess you may, alternatively to Thread.Sleep:
1 - Make your application as SINGLE INSTANCE (see the Properties of your Solution).
2- Add an Schedule Event into Task Scheduler of the Windows to call your application on each 15 minutes.
3- Your program will be terminated normally and will be called from Windows (or manually by user).
4- Since Single-Event you won´t have many instances of the application running at the same time - just one. So, even if the Task Scheduler starts a new instance, you may be sure that just one instance will be running.
Using a BackgroundWorker and a ManualResetEvent I think you can do what you have in mind.
public class LibraryBackgroundTimer : BackgroundWorker
{
private ManualResetEvent intervalManualReset;
public int Interval { get; set; }
public LibraryBackgroundTimer()
{
this.WorkerSupportsCancellation = true;
this.Interval = 1000;
}
protected override void OnDoWork(DoWorkEventArgs e)
{
while (!this.CancellationPending)
{
base.OnDoWork(e);
this.Sleep();
}
}
public void Start()
{
if (this.IsBusy)
return;
this.intervalManualReset = new ManualResetEvent(false);
this.RunWorkerAsync();
}
public void Stop()
{
this.CancelAsync();
this.WakeUp();
this.Dispose(true);
}
public void WakeUp()
{
if (this.intervalManualReset != null)
this.intervalManualReset.Set();
}
private void Sleep()
{
if (this.intervalManualReset != null)
{
this.intervalManualReset.Reset();
this.intervalManualReset.WaitOne(this.Interval);
}
}
}
using this class your timer can be stopped for a desired time and also it's capable of being waked up during the sleep time.
I hope this helps.
In an application that I am developing I will be using 2 threads to do various operations. (I will not go into detail here.) These threads work in loops, checking if there is work to be done, doing work, calculating the time they need to wait and waiting. (See below)
public Global : System.Web.HttpApplication
{
private static Thread StartingDateThread;
private static Thread DeadlineDateThread;
private static object o1;
private static object o2;
public static Thread GetStartingDateThreadInstance
{
get
{
if(StartingDateThread==null)
{
StartingDateThread=new Thread(new ThreadStart(MonitorStartingDates));
}
return StartingDateThread;
}
}
public static Thread GetDeadlineThreadInstance
{
get
{
if(DeadlineDateThread==null)
{
DeadlineDateThread=new Thread(new ThreadStart(MonitorDeadlines));
}
return DeadlineDateThread;
}
}
public static object GetFirstObjectInstance
{
get
{
if(o1==null)
{
o1=new object();
}
return o1;
}
}
public static object GetSecondObjectInstance
{
get
{
if(o2==null)
{
o2=new object();
}
return o2;
}
}
protected void Application_Start(object sender, EventArgs e)
{
GetStartingDateThreadInstance.Start();
GetDeadlineThreadInstance.Start();
//////////////////////
////Do other stuff.
}
public void MonitorStartingDates()
{
while(true)
{
//Check if there is stuff to do.
//Do stuff if available.
//Check if there will be stuff to do in the future and if there is, check
//the time to wake up.
//If there is nothing to do, sleep for a pre-determined 12 hours.
if(StuffToDoInFuture)
{
Monitor.Enter(GetFirstObjectInstance);
Monitor.Wait(WaitingTime);
Monitor.Exit(GetFirstObjectInstance);
}
else
{
Monitor.Enter(GetFirstObjectInstance);
Monitor.Wait(new TimeSpan(12, 0, 0));
Monitor.Exit(GetFirstObjectInstance);
}
}
}
public void MonitorDeadlines()
{
while(true)
{
//Check if there is stuff to do.
//Do stuff if available.
//Check if there will be stuff to do in the future and if there is, check
//the time to wake up.
//If there is nothing to do, sleep for a pre-determined 3 days and 12 hours.
if(StuffToDoInFuture)
{
Monitor.Enter(GetSecondObjectInstance);
Monitor.Wait(WaitingTime);
Monitor.Exit(GetSecondObjectInstance);
}
else
{
Monitor.Enter(GetSecondObjectInstance);
Monitor.Wait(new TimeSpan(3, 12, 0, 0));
Monitor.Exit(GetSecondObjectInstance);
}
}
}
As you can see these two threads are started in the Application_Start method in the asax file. They operate if there is stuff available to do and then they calculate the time period they need to wait and then they wait. However, as users of the web application do operations new records will be inserted into the database and there will be circumstances where any of the two threads will have to resume operation sooner than planned. So, say I have a method in my DataAccess class which inserts into the database new data. (See below)
public class DataAccess
{
///////////////
//
public void InsertNewAuction()
{
///Insert new row calculate the time
Monitor.Pulse(Global.GetFirstObjectInstance);
Monitor.Pulse(Global.GetSecondObjectInstance);
///
}
}
It seems like this is an invalid operation, because at the stage where the Monitor.Pulse is called from the InsertNewAuction method I get an exception. Something like "Object synchronization method was called from an unsynchronized block of code." Is there any way of doing this? Thanks for your help
As to the specific error you're seeing, this is because Monitor.Pulse must be called inside the Monitor lock, like this (I've used lock rather than Enter/Exit, as it's safer for making sure the lock is always released, since it uses a proper try/finally block):
lock (Global.GetFirstObjectInstance)
{
Monitor.Pulse(Global.GetFirstObjectInstance);
}
In regard to the more general design question here, it's often dangerous to expose lock objects as public (or even worse, global) fields. In particular, it can be a recipe for deadlocks when multiple global locks are exposed and acquired in differing orders or when you have cases like blocking dispatches to the UI thread while holding a lock. Consider looking into alternate ways to accomplish what you're after.
As noted in the other answer, you have to acquire the lock before you can call Monitor.Pulse() on the monitor object.
That said, your code has at least one other serious bug: you are not initializing the synchronization object in a thread-safe way, which could easily lead to two different threads using two different object instances, resulting in no synchronization between those threads:
public static object GetFirstObjectInstance
{
get
{
if(o1==null)
{
o1=new object();
}
return o1;
}
}
If two threads call this getter simultaneously, they each may see o1 as null and try to initialize it. Then each might return a different value for the object instance.
You should simply initialize the object in a initializer:
private static readonly object o1 = new object();
And then return it from the getter:
public static object GetFirstObjectInstance { get { return o1; } }
That addresses the thread-safety issue. But you still have other issues with the code. First, you should encapsulate synchronization in an object, not expose the actual synchronization object instance. Second, assuming you are going to expose the synchronization object, I don't understand why you bother with the property, since you made the field public. The field should be private if you want to use a property as well.
It would also be better if the property followed normal .NET naming conventions. A method that returned the object would have "Get" in the name, but a property would not. Just name it "FirstObjectInstance".
Also as noted by Dan, use lock everywhere you want to acquire the lock.
There may be other issues in the code as well...I didn't do a thorough review. But the above you need to fix for sure.