C# novice, question about controlling timers created in a constructor - c#

I have a class that creates a timer in the constructor.
The timer does exactly what I need it to do but I would also like to be able to use .Stop(); and .Start(); from the main program.
There is a lot more than this but this is enough to recreate my exact problem.
In the example below I have access to Monsters[index].M_timer but .Stop(); gives an error.
class Program
{
static void Main(string[] args)
{
int index = 0;
string name = "Spider";
monster[] Monsters = new monster[100];
Monsters[index] = Create_Monster(name);
/*
Monsters[1].M_timer.Stop(); <- not how I will be using this but I need the functionality here
*/
}
public static monster Create_Monster(string _name)
{
int timer = 0;
if (_name == "Spider")
{
timer = 4000;
}
monster build = new monster(false, timer);
return build;
}
}
class monster
{
public bool can_act;
public int _timer;
public object M_timer;
public monster(bool _can_act, int _timer)
{
can_act = _can_act;
Timer M_timer = new Timer();
M_timer.Interval = _timer;
M_timer.AutoReset = true;
M_timer.Enabled = true;
M_timer.Elapsed += TimerEvent;
}
public void TimerEvent(object source, ElapsedEventArgs e)
{
can_act = true;
}
}

An initial glance looks like you have a couple of issues. first, is scope. You have in your constructor a variable called M_timer which covers the class field M_timer. You are not acting upon the same objects here. You'd have to say something like this.M_timer = M_timer.
The second issue is that you'd have to cast the class field when you want to use it because it's a generic object. so you'd have to say something like ((Timer)Monsters[1].M_timer).Stop()

Damn, I should have given this just a few more minutes:
public object M_timer;
replaced with
public Timer M_timer;

Related

Referencing variable in class from within the same class

I am currently for the first time in need to rewrite my app into library. I have succes so far, but I need to somehow make auto repeated process, which could be started by simply camShield.start().
But I am not able to reference the enabled from anywhere. The idea here is that I would start thread with timer, which would be checking on the enabled variable. But to do that, I need another function, like stop(), which would set the enabled variable to false.
Is there any better way to implement such a function?
---EDIT----
I need to write functions CamShield.start() and CamShield.stop(), which would be able to access the CamShield.enabled variable.
Here is part of code, where I am trying to solve it (It is Class Library)
using SharpAdbClient;
using System;
using System.Diagnostics;
using System.Threading;
namespace BaReader
{
public class Private
{
public class CamShield
{
internal bool enabled = true;
public static void start()
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
Timer camShieldTimer = new Timer(tap, null, 0, 20000);
}).Start();
}
}
internal static void tap(Object o)
{
AdbClient.Instance.ExecuteRemoteCommand("input tap 600 900", Device.lookup(), null);
Debug.WriteLine("Tapped");
}
}
}
Thanks in advance for any ideas.
You have declared methods static and your variable enabled as non static so you were not able to access it,
public class CamShield
{
internal bool enabled = false;
public void start()
{
if(!enabled)
{
enabled = true;
//your code to start
}
}
public void stop()
{
if(enabled)
{
//your code to stop
enabled = false;
}
}
}
I am sure you can instantiate the CamShield class and access start and stop methods from outside.
In order to stop the thread, you need to kill it using Abort. The attached question will provide you with enough tools and knowledge to get there.
second, you cannot access the enabled because of your scope. Take another look at the code:
public class Private
{
public class CamShield
{
internal bool enabled = true;
public static void start()
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
Timer camShieldTimer = new Timer(tap, null, 0, 20000);
}).Start();
}
}
internal static void tap(Object o)
{
AdbClient.Instance.ExecuteRemoteCommand("input tap 600 900", Device.lookup(), null);
Debug.WriteLine("Tapped");
}
}
Your internal bool enabled is in the scope of CamShield class and won't be available to your tap method unless you initialize CamShield Class.
in order to use your internal bool enabled you need to declare it in your private class and then use it in tap:
public class Private
{
internal bool enabled = true;
public class CamShield
{
enabled = false;
public static void start()
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
Timer camShieldTimer = new Timer(tap, null, 0, 20000);
}).Start();
}
}
internal static void tap(Object o)
{
enabled = true;
AdbClient.Instance.ExecuteRemoteCommand("input tap 600 900", Device.lookup(), null);
Debug.WriteLine("Tapped");
}
}

C# threading - Main Thread gets stuck in inf loop

I'm running into a problem with my threading for my simple incremental game.
when I begin the thread it does not seem to be starting an actual thread so I get stuck in the endless loop in the thread RunThread method.
the way I'm doing threading in c# is inheriting from this base thread class somebody else on SO gave this code to allow you to inherit from Thread.
abstract class BaseThread
{
private Thread _thread;
protected BaseThread()
{
_thread = new Thread(new ThreadStart(this.RunThread));
}
// Thread methods / properties
public void Start() => _thread.Start();
public void Join() => _thread.Join();
public bool IsAlive => _thread.IsAlive;
// Override in base class
public abstract void RunThread();
}
that base thread is then inherited from. Person inherits from Base Thread.
abstract class Person : BaseThread
{
public BigInteger amt = new BigInteger(0);
public BigInteger pow = new BigInteger(1);
public BigInteger cost = new BigInteger(100);
public ResourceManagement res= ResourceManagement.Instance;
public static bool PeopleThreads = true;
public override void RunThread()
{
}
}
and at the lowest level, I have a Farmer this inherits from Person.
class Farmer : Person
{
public override void RunThread()
{
while (PeopleThreads)
{
Thread.Sleep(5000);
res.AddFood(amt * pow);
Thread.Sleep(5000);
res.AddFood(amt * pow);
res.subtractFromRes("Food", amt);
}
}
}
in my Thread manager class I am doing farmer.RunThread(); it seems to get me stuck in the while loop instead of creating a new thread. This is my first real attempt at c# threading ive done java threading before and thats why I wanted to be able to inherit from Thread. here is where I start my threads at.
class PeopleManager
{
Farmer farmers = new Farmer();
Lumberjack jacks = new Lumberjack();
Miner miners = new Miner();
private static PeopleManager people_Instance= new PeopleManager();
bool running = false;
static PeopleManager() { }//DO NOT PUT ANYTHING HERE
private PeopleManager() { }//DO NOT PUT ANYTHING HERE
public void StartThreads()
{
if (!running)
{
farmers.RunThread();
jacks.RunThread();
miners.RunThread();
running = true;
}
}
public static PeopleManager Instance { get{ return people_Instance; } }
I fixed my issue changed how I was running the threads from runThread to Start()
class PeopleManager
{
Farmer farmers = new Farmer();
Lumberjack jacks = new Lumberjack();
Miner miners = new Miner();
private static PeopleManager people_Instance= new PeopleManager();
bool running = false;
static PeopleManager() { }//DO NOT PUT ANYTHING HERE
private PeopleManager() { }//DO NOT PUT ANYTHING HERE
public void StartThreads()
{
if (!running)
{
farmers.Start(); //this instead of RunThread() made it run it
jacks.Start(); // run as a thread and not a method call
miners.Start();
running = true;
}
}
public static PeopleManager Instance { get{ return people_Instance; } }

Cancelling Thread Timer from another class

I'm attempting to implement the MSDN example (http://msdn.microsoft.com/en-us/library/swx5easy.aspx) for Thread.Timers in my own code.
I want to be able to cancel the timer when a certain user action is performed, however I can not dispose the timer, I suspect this is because I'm calling a method from another class so I need to adjust; but I don't know where.
Other than this, the timer works fine. Can anyone see why my timer will not cancel when btnconfigOpenConfig is called?
FYI I'm converting what was a worker process to a timed event.
public partial class Xservt : Window
{
internal class TimerStateObjClass
{
public int SomeValue;
public System.Threading.Timer SqlUpdateFromTwitterTimerReference;
public bool TimerCanceled;
}
internal void SomeMethod(){
TimerStateObjClass stateObj = new TimerStateObjClass();
stateObj.TimerCanceled = false;
stateObj.SomeValue = 100;
System.Threading.TimerCallback timerDelegate =
new System.Threading.TimerCallback(twit.hometimelineclass._sqlUpdateFromTwitterWorker_DoWork);
var sqlUpdateFromTwitterTimer = new Timer(timerDelegate, stateObj, 0,20000);
stateObj.SqlUpdateFromTwitterTimerReference = sqlUpdateFromTwitterTimer;
}
}
//action to perform which disposes the timer
private void btnconfigOpenConfig(object sender, RoutedEventArgs e)
{
TimerStateObjClass timerState = new TimerStateObjClass();
timerState.TimerCanceled = true;
}
//Actions the timer is calling, in another class
internal static void _sqlUpdateFromTwitterWorker_DoWork(object StateObj)
{
Xservt.TimerStateObjClass state = (Xservt.TimerStateObjClass) StateObj;
if(state.TimerCanceled)
{
state.SqlUpdateFromTwitterTimerReference.Dispose();
}
//some work
}
As Hans pointed out in the comments, you need to keep a reference to TimerStateObjClass you originally created. You can then use that to set TimerCanceled.
public partial class Xservt : Window
{
internal class TimerStateObjClass
{
public int SomeValue;
public System.Threading.Timer SqlUpdateFromTwitterTimerReference;
public bool TimerCanceled;
}
TimerStateObjClass stateObj; //THIS IS THE ORIGINAL STATE OBJ
internal void SomeMethod()
{
stateObj = new TimerStateObjClass();
stateObj.TimerCanceled = false;
stateObj.SomeValue = 100;
System.Threading.TimerCallback timerDelegate = new System.Threading.TimerCallback(twit.hometimelineclass._sqlUpdateFromTwitterWorker_DoWork);
var sqlUpdateFromTwitterTimer = new Timer(timerDelegate, stateObj, 0, 20000);
stateObj.SqlUpdateFromTwitterTimerReference = sqlUpdateFromTwitterTimer;
}
//action to perform which disposes the timer
private void btnconfigOpenConfig(object sender, RoutedEventArgs e)
{
//HERE WE CAN GET AT THE ORIGINAL STATE OBJ
stateObj.TimerCanceled = true;
}
}
//Actions the timer is calling, in another class
internal static void _sqlUpdateFromTwitterWorker_DoWork(object StateObj)
{
Xservt.TimerStateObjClass state = (Xservt.TimerStateObjClass)StateObj;
if (state.TimerCanceled)
{
state.SqlUpdateFromTwitterTimerReference.Dispose();
}
//some work
}
You need to store reference to your timer (or class that references the timer) somewhere in your class.
To stop the timer there is not need to dispose it. You can just call timer.Change(-1, -1);. That will allow to re-enable timer again by calling timer.Change(dueTimeInMs, intervalInMs);
You code should be something like that:
public partial class Xservt : Window
{
private Timer timer = new Timer(o => DoSomething());
private void StartTimer()
{
var period = 5 * 1000; // 5 sec
timer.Change(0, period);
}
private void StopTimer()
{
timer.Change(-1, -1);
}
}
Then call StartTimer to run it and StopTimer to stop respectively.
Also note that if there is any chance that DoSomething will run longer than timer interval that would result in running that method in more than one thread concurrently. To avoid that DO NOT use Timer's interval but use dueTime instead:
private Timer timer = new Timer(o => {
DoSomething();
StartTimer();
});
private void StartTimer()
{
var period = 5 * 1000; // 5 sec
timer.Change(period, 0);
}
In this timer is trigrered to run only once but after each run it gets re-triggered.

how to return values from one class to another?

I'm making a program that has three classes:
Output class receives data from other two classes, writes to two new strings, combines with special formatting to another string and outputs it
AidaF class has a method that returns a value(a string) every second
GmailF class has a method that returns a value(a string) every minute or so
so i tired using return string; to return the data from classes 2 and 3 to the first class but that just returns the value to the current class, not to the first class.
Here is this code I'm working on, slimmed down a lot though. but basics are there.
namespace Final
{
public class Output
{
public static void Main()
{
Console.WriteLine(gml + aida);
}
}
public class AidaF
{
private static System.Timers.Timer aTimer;
public static void AMain()
{
aTimer = new System.Timers.Timer(1000);
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 1000;
aTimer.Enabled = true;
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
...
reader.ReadToFollowing("value");
aida.Append(reader.ReadElementContentAsString()).Append(",");
return aida;
...
}
}
public class GmaillF
{
private static System.Timers.Timer gTimer;
public static void GMain()
{
gTimer = new System.Timers.Timer(200000);
gTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent1);
gTimer.Interval = 200000;
gTimer.Enabled = true;
}
private static void OnTimedEvent1(object source, ElapsedEventArgs e)
{
CheckMail();
}
public static string CheckMail()
{
...
gml.Append(reader.ReadElementContentAsString()).Append(",");
return gml;
...
}
}
}
You need to call the exposed static methods from the calling class in order to get this to work, so for example your main would look more like this:
public static void Main() {
Console.WriteLine(GmailF.CheckMail() + AidaF.OnTimedEvent());
}
I'm just guessing that CheckMail and OnTimedEvent are the strings you are trying to return. Both CheckMail and OnTimedEvent have to be public static strings for the above to work.

Interested In Feedback About My Timeout Class

Many areas in a project I'm working on have a simple timeout check which basically runs code through a try loop until it succeeds or 10 seconds elapses.
class Timeout {
private readonly DateTime timeoutDate;
public bool FlagSuccess;
public Timeout() {
timeoutDate = DateTime.UtcNow.AddSeconds(10);
flagSuccess = false;
}
public bool continueRunning() {
if (!flagSuccess && DateTime.UtcNow < timeoutDate) return true;
else return false;
}
}
Here is an example of the class in use:
Timeout t = new Timeout();
while (t.continueRunning()) {
try {
//PUT CODE HERE
t.flagSuccess = true;
}
catch(Exception e) {
Console.WriteLine(e.Message);
}
}
Before I implement this, is there a better and more standard way to do this? What I have above is based on my blind intuition.
Use .NETs Timer class(es):
using System.Timers;
public static void Main() {
Timer t = new Timer();
t.Elapsed += new ElapsedEventHandler(ActionWhenFinished);
t.Interval = 10000;
t.Start();
}
public static void ActionWhenFinished()
{
// cancel any action
}
Your Timeout class will block the current thread it is running in, which isn't the case with System.Timer.
I'd suggest changing your loop to a do-while loop, so that you're guaranteed to run the loop at least once even if your thread gets momentarily waylaid between setting up the timeout and starting the loop. Also, I'd suggest that it may be helpful to have the Timeout class include a RemainingMilliseconds property, and maybe RemainingMillisecondsUpTo(Integer N) function, which could be passed to various block-or-timeout routines.
Looks kind of like a busy loop to me, but here's how you'd do it with a StopWatch.
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
timer.Start();
bool complete;
while( timer.ElapsedMilliseconds < 10000 && !complete)
{
//Do stuff
// and someday... complete = true;
}
You could wrap that up into a simple class as well if you like.
class AgingWait
{
System.Diagnostics.Stopwatch _watch = new System.Diagnostics.Stopwatch();
int maxMilliseconds;
bool forceExpire;
public bool Expired
{
get { return forceExpire || maxMilliseconds < _watch.ElapsedMilliseconds; }
}
public AgingWait(int milli)
{
_watch.Start();
maxMilliseconds = milli;
}
public void Expire()
{
forceExpire = true;
}
}
to use
AgingWait waiter = new AgingWait(1000);
while (!waiter.Expired)
{
if (condition)
waiter.Expire();
}

Categories

Resources