C# How to notify other classes with a single timer? - c#

I am trying to make a global timer where everything that needs to be notified after certain time has passed.
For instance, in a game, there would be buffs and attack cool down timers and item cool down and much more.
Managing them separately is fine, but how would I make them all to run on same timer?
I was tried using SortedList with a float as key and a delegate as value to be simply invoked when time is up, but I cant seem to manage it. Tried delegate with Generic parameter but I can't put that into a sorted list.
Can anyone point me in the right direction?

I can point out 2 options:
Create an interface like TimerControlled (all names can be changed) With a method TimerTick(whatever arguments you need) (and others if needed) , which implements your timer tick logic for that class. Implement the interface the on each class that uses timer dependent mechanics. Finally on your base (logic) class add all of your TimerControlled object to an array (of TimerControlled) which will allow you to cycle through that array and call TimerTick methods of those object with 2 lines of code.
Interface:
interface TimerControlled
{
void TimerTick();
}
Implement it in each of your classes:
public class YourClass: TimerControlled{
....
public void TimerTick(){
advanceCooldown();
advanceBuffTimers();
}
}
finally add your classes to a list of TimerControlled:
class YourLogicClass{
List<YourClass> characters= new List<YourClass>();
private timer;
List<TimerControlled> timerControlledObjects = new List<TimerControlled>();
...
public void Initialize(){
... //your code, character creation and such
foreach(YourClass character in characters){ //do the same with all objects that have TimerControlled interface implemented
timerControlledObjects.add(character);
}
timer = new Timer();
timer.Tick += new EventHandler(timerTick)
timer.Start();
}
public void timerTick(Object sender, EventArgs e){
foreach(TimerControlled timerControlledObject in timerControlObjects){
timerControlledObject.TimerTick();
}
}
}
(not a very good option in the long run) Static timer in a static class, like Global.timer, which will mean only 1 instance of that timer will exist. Then attach an event handler to timer from each relevant class to handle timer ticks.
Code:
public static class Global{
//I usually create such class for global settings
public static Timer timer= new Timer();
}
class YourLogicClass{
public void Initialize(){
...
Global.timer.Start();
}
}
class YourClass{
public YourClass(){
Global.timer.tick += new EventHandler(timerTick);
}
private void timerTick(Object sender,EventArgs e){
advanceCooldowns();
advanceBuffTimers();
}
}
Keep in mind that I've written the code off the top of my head, so some syntax errors might be there, but the logic is right.
If you have further questions regarding the answer ask away.

Related

is there a better way to get information from another class?

I'm working on a program and I wanted to know the best way I can get information from one class to another.
My purpose is to get information from MyTimer to the Program class about how much "ticks" the timer did.
** I don't want from the class MyTimer to be dependent on the Program class (Like by using Program.SetUpdate()). MyTimer class should work with every class without changing his code.
I've already tried using public static method to send the information.
class Program
{
private static int _count;
private static MyTimer _myTimer;
static void Main(string[] args)
{
_count = 0;
_myTimer = new MyTimer() { Timer_Interval = 100 };
_myTimer.Start();
do
{
Console.WriteLine("Press q to quit.");
} while (Console.ReadKey().KeyChar.ToString().ToLower() != "q");
_myTimer.Stop();
}
public static void SetUpdate(int count)
{
_count = count;
Print();
}
private static void Print()
{
Console.WriteLine(_count);
}
}
class MyTimer
{
private Timer _timer;
private int _ticks;
public int Timer_Interval { get; set; }
public MyTimer()
{
_timer = new Timer();
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
}
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
Program.SetUpdate(_ticks);
_ticks++;
}
public void Start()
{
if (Timer_Interval == 0)
throw new InvalidOperationException("_timer interval can not be 0.");
_ticks = 0;
_timer.Interval = Timer_Interval;
_timer.Start();
}
public void Stop()
{
_timer.Stop();
}
}
The output is 1,2,3... until you press q/Q
I've tried to do it as simple as I can only to show you the concept.
So I created a class named Program that call MyTimer class.
MyTimer class is simply like a timer: stop,start and elapsed. Each interval it makes a "tick".
You'd normally fix this sort of issue by establishing a "direction". E.g. here it feels natural that it should be "from" Program "to" MyTimer. In that given direction, it's perfectly fine to make direct method calls, access properties, etc.
When you need information to flow in the other direction, that's when you use events. MyTimer raises an event and Program can have a handler. In this way, MyTimer doesn't know which classes are creating it/working with it or even how many event handlers have been installed.
I think Damien nailed it pretty much for this scenario.
Yet, I'd like to propose an alternative: Using a shared State Object.
You could define a State class, which does nothing else than hold the value of the tick-count.
You'd instanciate it in Program and pass it to the MyTimer. Mind that both classes now share the same instance (possibly introducing threading/concurrency issues if in multithreaded context).
MyTimer then would update the state on that shared Object.
Examples are Model/ViewModel classes in MVVM/WPF where you would bind some Control's property to that object's property.
Mind that Program wouldn't know of a occurring change out of the box. So that would have to be handled additionally. Either again via an Event, some "Observer Pattern" or similar.
As I said, events are the way to go here but I thought it couldn't hurt to suggest an alternative way of inter-class communication.

Trigger a custom event for an "external" value change

I'm reading values from a certain process memory. Let's say that I fetch them in the following way:
var foo = memoryService.GetFoo();
var bar = memoryService.GetBar();
Since it doesn't exist any events for memory changes, I would like to create custom events using polling (if you don't have any other suggestions).
Since I don't know when the values might change, the polling interval has to be set to a suitable value. I don't know how to actually write this, but something like this might do (not sure if it compiles):
public class MemoryChange : INotifyPropertyChanged
{
private Timer _timer;
public SomethingChanged(double polingInterval)
{
_timer = new Timer();
_timer.AutoReset = false;
_timer.Interval = polingInterval;
_timer.Elapsed += timer_Elapsed;
_timer.Start();
}
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
}
}
Do I need to create one class that implements INotifyPropertyChanged for each value (foo and bar in this case)?
Is there any way to make it run on a non blocking thread (using a Task perhaps?)?
Do I have to use polling to make this work?
Any input is much appreciated!
If you have access to your MemoryService from your main view model, then you could define a simple delegate to solve your problem.
In your MemoryService, define the delegate and related property:
public delegate void DataUpdate(object someData);
public DataUpdate OnDataUpdate { get; set; }
In the parent view model, attach a handler for the delegate:
MemoryService memoryService = new MemoryService();
memoryService.OnDataUpdate += MemoryService_OnDataUpdate;
Back in MemoryService when the data is ready:
var foo = memoryService.GetFoo();
// Always check for null
if (OnDataUpdate != null) OnDataUpdate(foo);
Now in the parent view model:
public void MemoryService_OnDataUpdate(object someData)
{
// Do something with the new data here
}
You can find out more about using delegate objects from the Delegates (C# Programming Guide) page on MSDN.
I am not sure in what context you will be using your memory service though I will give it a try to answer your quesiton.
Yes, you will have to implement INotifyPropertyChanged in every class.
Yes there is a way, Google knows it.
You can use polling or you could listen to PropertyChanged event. That would be the callback approach where you get notified when a changes happened.

Is it possible for instance to destroy/delete self?

NOTE: I'm interested in C#,Java and C++ most, but as this is the more academic question any language will do.
I know that this problem is solvable from outside, by using appropriate methods of given languages (calling free, Dispose, or by removing all references to instance).
My idea is that I create an instance, and in the constructor , I start the private timer. When the timer ends it will call some instance method and destroy the variable.
I think that in C# it should be possible to call Dispose on self, when the IDisposable is implemented, but this would not destroy the instace.
In C++ I could call the destructor, but that would lead to the memory leak, plus it is really bad practice.
In Java I have no clue, assigning to this it's not possible as it is final field.
So is there any way for instance, to destroy self?
Your question is very interesting, and I don't know of any other way to do so in C# but to force from the inside of the instance its destruction from the outside. So this is what I came up with to check if it is possible.
You can create the class Foo, which has event that is fired when the specific interval of the timer elapses. The class that is registered to that event (Bar) within event de-registers the event and sets the reference of the instance to null. This is how I would do it, tested and it works.
public class Foo
{
public delegate void SelfDestroyer(object sender, EventArgs ea);
public event SelfDestroyer DestroyMe;
Timer t;
public Foo()
{
t = new Timer();
t.Interval = 2000;
t.Tick += t_Tick;
t.Start();
}
void t_Tick(object sender, EventArgs e)
{
OnDestroyMe();
}
public void OnDestroyMe()
{
SelfDestroyer temp = DestroyMe;
if (temp != null)
{
temp(this, new EventArgs());
}
}
}
public class Bar
{
Foo foo;
public Bar()
{
foo = new Foo();
foo.DestroyMe += foo_DestroyMe;
}
void foo_DestroyMe(object sender, EventArgs ea)
{
foo.DestroyMe -= foo_DestroyMe;
foo = null;
}
}
And in order to test this, you can set up a button click within a Form, something like this, and check it in the debugger:
Bar bar = null;
private void button2_Click(object sender, EventArgs e)
{
if(bar==null)
bar = new Bar();
}
So next time when you click the button, you will be able to see that Bar instance still exists but the Foo instance within it is null although it has been created within the Bar's constructor.
C++: If an object was allocated dynamically, it can delete its this pointer in its own function, provided the this pointer is never used again after that point.
No, there is no way to achieve what you are trying to do in C#.
If you consider an example :
public class Kamikadze {
......
private void TimerTick(..)
{
....
if(itsTime) {
DestroyMe();
}
}
.....
}
var kamikadze = new Kamikadze ();
after a while DestroyMe() will be called that cleans internal data.
But the reference kamikadze (pointer if you wish) is still valid and points to that memory location, so GC will not do anything, will not collect it, and instance of Kamikadze will remain in memory.
For C++ take a look at this:
http://www.parashift.com/c++-faq/delete-this.html
.
The closest thing in C# that I can think of:
On creation, every object stores a reference to itself in the GC root, e.g. by putting the reference into a class static list. Outside of the class, nobody is allowed to store (strong) references to the object. Everybody uses a WeakReference and checks if the Target is still IsAlive before touching the object. That way, the only thing that is keeping the object alive is the static reference.
When the object decides to kill itself, it simply removes the reference from the list. Sooner or later, the GC collects the object. Or, if you are really impatient, call GC.Collect() (ouch!).
But I really really would not recommend this solution!
It's much better put some flag into the class/object to signal whether it's still alive and make everybody check this flag before using the object. This can be combined with the IDisposable solution.
In C++, instances committing suicide are an integral part of the Finite State Machine Pattern:
//Context class contains a pointer to a State object.
void BattleshipGame::SetGameState(IState* state) {
game_state = state;
}
void BattleshipGame::Loss() {
game_state->Loss(this);
}
void BattleshipGame::Idle() {
game_state->Idle(this);
}
void BattleshipGame::FlyBy() {
game_state->FlyBy(this);
}
void BattleshipGame::Attack() {
game_state->Attack(this);
}
void BattleshipGame::Win() {
game_state->Win(this);
}
void BattleshipGame::Load() {
game_state->Loading(this);
}
//State base class contains methods for switching to every state.
class IState {
public:
virtual void Loading(BattleshipGame* context);
virtual void Idle(BattleshipGame* context);
virtual void FlyBy(BattleshipGame* context);
virtual void Attack(BattleshipGame* context);
virtual void Win(BattleshipGame* context);
virtual void Loss(BattleshipGame* context);
protected:
private:
};
//Implementations in the State base class are defined, but empty.
//Derived States only call what they need:
void StateIdle::Loss(BattleshipGame* context) {
//context->SetGameState(new StateLoss());
context->SetGameState(new StateLoss(context));
delete this;
}
void StateIdle::Idle(BattleshipGame* context) {
context->SetGameState(new StateIdle());
delete this;
}
void StateIdle::FlyBy(BattleshipGame* context) {
context->SetGameState(new StateFlyBy());
delete this;
}
void StateIdle::Win(BattleshipGame* context) {
context->SetGameState(new StateWin());
delete this;
}
//Similar design for all other states...
In C#, you're right you can implement IDisposable but the trick is instead of calling Dispose method make use of the using statement.
class Program
{
static void Main(string[] args)
{
using (MyClass obj = new MyClass())
{
obj.SayHello();
}
// obj.SayHello(); // Error: The name 'obj' does not exist in the current context
}
}
class MyClass : IDisposable
{
public void SayHello()
{
Console.WriteLine("Hello");
}
public void Dispose()
{
// Do something (e.g: close some open connection, etc)
}
}
For Reference: microsoft-docs/using-statement
I recommend using NFTLKEY. You can easily get it from the Nuget package. Best of all, it's open source: github project
Easier to understand than the examples here

unit testing system.timers.timer

I've been reading over the questions about unit testing with timers and threading. I found the SO question about unit testing system.threading.timers, but I need to unit test a system.timers.timer and a wrapper class doesn't seem to work quite as smoothly for this one.
I just need to know how to mock the timer and/or system time in order to unit test against it. I can't seem to find this anywhere on google.
edit & update:
It makes sense that if I extract the timer by wrapping it as below, I can generate a timer and use mocking to replace it with a different timer. The relevant part is then to take that timer that I'm injecting at runtime (the original, not a mock) and test it's elapsed event code.
What stops you from wrapping this one?
public interface ITimer
{
void Start(double interval);
void Stop();
event ElapsedEventHandler Elapsed;
}
That's pretty much all your interface needs. Let's see how this could go (note that you could of course expose more Timer properties, but that's pretty much basic stuff that should be enough):
public class MyTimer : ITimer
{
private Timer timer = new Timer();
public void Start(double interval)
{
timer.Interval = interval;
timer.Start();
}
public void Stop()
{
timer.Stop();
}
public event ElapsedEventHandler Elapsed
{
add { this.timer.Elapsed += value; }
remove { this.timer.Elapsed -= value; }
}
}
Now, how would you utilize this in your testing (assuming we're using FakeItEasy as mocking framework of choice):
var timerFake = A.Fake<ITimer>();
var classUnderTest = new MyClass(timerFake);
// tell fake object to raise event now
timerFake.Elapsed += Raise.With<ElapsedEventArgs>(ElapsedEventArgs.Empty).Now;
// assert whatever was supposed to happen as event response, indeed did
Assert.That(classUnderTest.ReceivedEvent, Is.True);
Example above actually does test the code that happens once the event on timer is raised. Consider MyClass looking like this:
public class MyClass
{
private ITimer timer;
public MyClass(ITimer timer)
{
this.timer = timer;
this.timer.Elapsed += TimerElapsedHandler;
}
public bool ReceivedEvent { get; set; }
private void TimerElapsedHandler(object sender, ElapsedEventArgs e)
{
ReceivedEvent = true;
}
}
In the test, we force timer to raise when we need it, and we check whether code in TimerElapsedHandler executed, by asserting ReceivedEvent property was set. In reality, this method might do more than that, but that will only change the way we do assertions - idea remains the same.
Edit: You can also try Moles, a framework that allows you to generate fakes of any framework types/methods. However, if mocking timer was all you wanted, I'd go with wrapper approach.
You need to test the timer or test the code executed in each event? If so, you can put that logic in another class and just test that. You can trust the timer will call it...

Timer within Thread within Windows Service

I cant figure out how to proceed the best way with this problem.
Right now I have a windows service which only task is to gather data from a database with a specific DSN and then send out an email if the data is valid. The service contains a timer which ticks every 5 minuts and performs the tasks above.
Now I need to re-write the windows service to be able to run on more than 1 DSN.
I was thinking of making several threads inside the windows service and then again have a seperat timer inside each thread.
Is this a good idea and how can this be done? I want to avoid having a windows service for each DSN.
Ill try to draw it if I dont make any sense
Windows Service
Thread1(DSN1)-----------------------------Thread2(DSN2)----------------------Thread3(DSN3)
Timer(ticks every X minuts)-----------------Timer(same)-------------------------Timer(same)
Logic()---------------------------------------------Logic---------------------------------Logic()
Hope my problem makes sense :)
As far as I Know each timer represents a thread on its own. Knowing this, I would try to dynamically create timer objects for each given dsn.
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
private List<GetDataFromDSN> list = null;
protected override void OnStart(string[] args)
{
list = new List<GetDataFromDSN>();
// assume args contains your given dsn values
foreach (string dsn in args)
{
GetDataFromDSN newObj = new GetDataFromDSN();
newObj.DSN = dsn;
list.Add(newObj);
newObj.Start();
}
}
}
public class GetDataFromDSN
{
public string DSN { get; set; }
private Timer timer = null;
private double interval = 1000*60*5; // 5 minutes interval
public GetDataFromDSN()
{
// init your object
timer = new Timer(interval);
timer.Elapsed +=new ElapsedEventHandler(timer_Elapsed);
}
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
// do what ever you want
}
public void Start() // or even make timer public
{
timer.Start();
}
public void Stop()
{
timer.Stop();
}
}
Do each of the DSNs need to be on a separate Thread?
If you were to encapsulate the Email retrieval and validation logic within some sort of service that the Thread invoked, the fact that there were multiple DSNs could be hidden from the scheduling thread. For instance, an IEmailService might have the following contract:
public interface IEmailService
{
void SendEmailsToValidAddresses();
}
and the implementation might look something like this:
public class MultipleSourcesEmailService : IEmailService
{
private IEnumerable<IDatabaseSource> databases;
public EmailService(params IDatabaseSource[] sources)
{
databases = new List<IDatabaseSource>(sources);
}
public void SendEmailsToValidAddresses()
{
foreach(var database in databases)
{
var emailAddresses = database.SelectAllEmailAddresses();
ValidateAndSendEmailsTo(emailAddresses);
}
}
public void ValidateAndSendEmailsTo(IEnumerable<string> emailAddresses)
{
// Perform appropriate logic
...
}
}
In this way, your timer logic can remain the same and on a single Thread whilst the concern of sending emails is separated into the IEmailService. This also means that you could implement a SingleSourceEmailService and a MultipleSourceEmailService and swap the multiple sources in when you're code complete and the consumer of the service need never know.
Of course, the EmailService as implemented above will SendEmails from multiple sources sequentially - if you need it to run in parallel you could change the EmailService to kick off a new Thread for each of the DSNs that you have, you could even call it the: MultiThreadedMultipleSourceEmailService but as a consumer of the IEmailService your scheduling will never know the difference.
Use a backgroundworker.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Just start one for each DSN, very smooth and easy to use.
Try using System.Threading.Timer
Here is sample code from my project, Hope this helps
public void StartDSNTimers()
{
_tmr1 = new Timer(CheckMessages, dsn1, 0, 60000);
_tmr2 = new Timer(CheckMessages, dsn2, 0, 60000);
_tmr3 = new Timer(CheckMessages, dsn3, 0, 60000);
}
private void CheckMessages(object obj)
{
//Logic
}

Categories

Resources