TimerTick wont trigger ever - c#

I've created simple class which will behave like my service class, because I've included that class in Topshelf.
Class is simple it just imports some files to db and prints it after it.
Here is the definition:
class ConverterService
{
private FileSystemWatcher _watcher;
private readonly System.Timers.Timer timer;
public ConverterService()
{
ImportAllFiles();
timer = new System.Timers.Timer(10){AutoReset = true};
timer.Elapsed += Timer_Elapsed;
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
PrintFiles();
}
catch(Exception ex)
{
}
}
But problem is Timer_Elapsed is never executed..
I don't know why..
ImportAllFiles() triggers successfully but Timer_Elapsed method is never fired, and I wanted to execute that method every second for example
Thanks guys
Cheers

You need to call timer Start():
timer = new System.Timers.Timer(10){AutoReset = true};
timer.Elapsed += Timer_Elapsed;
timer.Start();
or alternative :
timer.Enabled = true;

Related

Pass function as parameter C# (Timer.Enable)

i'm learning c# and i'm trying some stuff with the System.Timers.Timer, and i'm having a problem, cause i want to make a function that receives another function so i could 'bind' it to the timer.Elapsed event. I'm trying to build something like:
public void timerElapsedMethod(my method)
{
timer.Elapsed += my method;
}
There is a way where i can do that ?
edit 1:
Guys, what i'm trying to do is, baiscally encapsulate the timer class, so i want a user to call my function passing his function as an argument.
Like:
class MyTimer
{
public static Timer timer;
public MyTimer()
{
timer = new Timer();
}
internal void *timerElapsedMeth*(Action<object, ElapsedEventArgs> method)
{
timer.Elapsed += (if i put method here i get an error);
}
}
Now imagine someone wants to use my class and wanna do something like:
class SomeUserRandomClass
{
public static MyTimer mytimer;
public SomeUserRandomClass()
{
mytimer = new MyTimer();
}
public void userRandomMethod()
{
some code...
}
myTimer.*timerElapsedMeth*(userRandomMethod);
}
Is it possible to do that ?
Thx
You can do it something like the following.
I wouldn't try to try and asign it to the event directly. But hide the event details
class MyTimer
{
private readonly Action _userAction;
private Timer timer;
public MyTimer(Action userAction)
{
_userAction = userAction;
timer = new Timer();
timer.Elapsed += Timer_Elapsed;
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
_userAction?.Invoke();
}
}
You can accomplish this using lambda expressions.
public void timerElapsedMethod(Action myMethod) {
var timer =new Timer();
timer.Elapsed += (s, e) => {
myMethod?.Invoke();
};
}
if myMethod needs parameters, you can edit the timerElapsedMethod to take parameters.
public void timerElapsedMethod(Action myMethod, int param) {
var timer =new Timer();
timer.Elapsed += (s, e) => {
myMethod?.Invoke(param);
};
}
Hope this can help.
Create an event in your wrapper class which is fired when the timer event is fired.
class MyTimer
{
// Is there a reason you want this timer to be public? Otherwise make it private.
public static Timer timer;
public event EventHandler<ElapsedEventArgs> OnTimerEvent;
public MyTimer()
{
timer = new Timer();
}
private static void OnTimedEvent(Object sender, ElapsedEventArgs e)
{
OnTimerEvent?.Invoke(this, e);
}
}
Using your timer class:
class SomeUserRandomClass
{
private static MyTimer mytimer;
public SomeUserRandomClass()
{
mytimer = new MyTimer();
myTimer += TimerEventHandler; // Register to the event
}
public void userRandomMethod()
{
some code...
}
private static void TimerEventHandler(Object sender, ElapsedEventArgs e)
{
// Handle the event
}
}
Make sure to "unregister" the event when you Dispose your SomeUserRandomClass:
myTimer -= TimerEventHandler;

Can't start timer from a different thread

I am working on a program where I need to activate a timer from a different thread. I've shortened the code to this example below.
static class Program
{
public static System.Windows.Forms.Timer TimerVideo = new System.Windows.Forms.Timer();
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
TimerVideo.Interval = 1000;
TimerVideo.Tick += new EventHandler(TimerVideo_Tick);
new Thread(() =>
{
test RunTimer = new test();
RunTimer.StartTimer();
}).Start();
Application.Run();
}
private static void TimerVideo_Tick(object sender, EventArgs e)
{
Console.WriteLine("Running");
}
}
class test
{
public void StartTimer()
{
Program.TimerVideo.Start();
}
}
Even if I have to code the timer in the class that would be fine with me, but I did try that and it didn't work either, namely the timer did not fire and nothing was printed out to the console.
System.Windows.Forms.Timer is meant to be run from a UI thread. If you want a timer that fires on a different thread, you can use System.Timers.Timer, e.g.:
TimerVideo = new System.Timers.Timer();
TimerVideo.Interval = 1000;
TimerVideo.Elapsed += (o, e) => Console.WriteLine("Running");
TimerVideo.Start();
Since the timer was created in other thread, you need to call it's methods using Invoke.
https://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/zyzhdc6b(v=vs.110).aspx

Using System.Timers.Timer in winforms Presenter

How to set System.Timers.Timer in presenter in order to elapse in view thread?
Environment: C#, .NET 4.0 CP, WinForms
My current cod is here, but it doesn't work. I have to additionally "Invoke" in the view.
I cast view to ISynchronizeInvoke to build the code. Casting to Control doesn't help.
public class GeneratorPagePresenter : IGeneratorPagePresenter
{
private IGeneratorPage view;
private Timer timer;
public void SetView(IGeneratorPage generatorPage)
{
view = generatorPage;
timer = new Timer();
timer.Interval = 1000;
timer.AutoReset = true;
timer.SynchronizingObject = (ISynchronizeInvoke) view;
timer.Elapsed += Timer_Elapsed;
}
void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
view.UpdateProgress(percentage);
}
}
EDIT
Thanks to AnPasant comment (which mysteriously disapeared). I set SynchronizingObject as a parameter. It works fine, but the code looks something strange.
public void SetView(IGeneratorPage generatorPage, ISynchronizeInvoke sync)
{
view = generatorPage;
timer = new Timer();
timer.Interval = 1000;
timer.AutoReset = true;
timer.SynchronizingObject = sync;
timer.Elapsed += Timer_Elapsed;
}
This method is called by View as follows:
presenter.SetView(this, this);
The thing is that you have to switch Synchronization Context somewhere. ViewModel in this case schould be created in UI Thread.
private IGeneratorPage view;
private Timer timer;
private SynchronizationContext uiSyncContext;
public GeneratorPagePresenter()
{
uiSyncContext = SynchronizationContext.Current;
}
public void SetView(IGeneratorPage generatorPage)
{
view = generatorPage;
timer = new Timer();
timer.Interval = 1000;
timer.AutoReset = true;
timer.Elapsed += Timer_Elapsed;
}
void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
uiSyncContext.Post((state) => view.UpdateProgress(percentage), null);
}

System.Timers.Timer Elapsed Exception handling in Library

I would like handle the occurred System.Timers.Timer elapsed exception (in my DLL library) within my WPF application. But I'm not be able to do that. It throws in my DLL library and the application will crashing...
Does anybody know how I can solve the problem?
Here my code:
public partial class MainWindow : Window
{
MyClass _myClassInstance = null;
public MainWindow()
{
InitializeComponent();
try
{
_myClassInstance = new MyClass();
}
catch(Exception ex)
{
//Here i would like to receive the exception
//But it never goes in there
MessageBox.Show(ex.Message);
}
}
}
public class MyClass
{
private System.Timers.Timer _timer = null;
public MyClass()
{
_timer = new Timer();
_timer.Interval = 2000; //2 Seconds
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Start();
ConnectTo();
}
void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
//If timer is elapsed I have to raise an exception
throw new Exception("It's taking longer than expected. Progress cancelled!");
}
private void ConnectTo()
{
//Just an example implementation
//Do something!!
//Connect to SerialPort and wait for correct response
//If connected than
_timer.Stop();
}
}
The exception is thrown on another thread (as per your choice for Timing.Timer).
Try this inside 1 assembly: you can't catch it either. That it's in a DLL doesn't matter.
You can only solve this by re-thinking the problem and picking another solution.
The exception is happening inside the event. This is run on another thread, therefore it's never going to make it back to your original thread.
Two possibilities to do this differently.
Your serial port com library has some sort of timeout functionality (maybe), just use it instead.
Do your serial port checking on a separate tread. If your time runs out, kill that thread.
public class MyClass
{
private System.Timers.Timer _timer = null;
private Thread t;
public MyClass()
{
_timer = new Timer();
_timer.Interval = 2000; //2 Seconds
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Start();
t = new Thread(new ThreadStart(ConnectTo));
t.Start();
t.Join();
}
void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
//If timer is elapsed I have to raise an exception
if (t != null)
t.Abort();
}
private void ConnectTo()
{
//Just an example implementation
//Do something!!
//Connect to SerialPort and wait for correct response
//If connected than
_timer.Stop();
}
}
As an alternative approach, rather trying to control your application flow with Exceptions, you could use events instead e.g.
public partial class MainWindow : Window
{
MyClass _myClassInstance = null;
public MainWindow()
{
InitializeComponent();
_myClassInstance = new MyClass();
_myClassInstance.TimedOut += delegate (object sender, EventArgs e) {
((MyClass)sender).CancelConnect();
MessageBox.Show("Timeout!");
};
_myClassInstance.ConnectTo();
}
}
...
public class MyClass
{
Timer _timer = new Timer();
public event EventHandler TimedOut;
void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
OnTimedOut();
}
private void OnTimedOut()
{
var handler = TimedOut;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
public void ConnectTo(int timeout = 2000)
{
CancelConnect();
_timer.Interval = timeout; // pass timeout in so it's flexible
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Start();
// do connect stuff...
_timer.Stop();
}
public void CancelConnect()
{
_timer.Stop();
// cancel connect stuff...
}
}
I think you had far too much going on in your constructor for MyClass so I moved it into ConnectTo which you invoke directly from your MainWindow.
Not work:
MessageBox.Show(e.Message); doen's throw
public class MyClass
{
private System.Timers.Timer _timer = null;
private Thread t;
public MyClass()
{
try
{
_timer = new System.Timers.Timer();
_timer.Interval = 5000; //2 Seconds
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Start();
t = new Thread(new ThreadStart(ConnectTo));
t.Start();
t.Join();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
//If timer is elapsed I have to raise an exception
if (t != null)
{
t.Abort();
}
}
private void ConnectTo()
{
//Just an example implementation
//Do something!!
try
{
//Connect to SerialPort and wait for correct response
using (SqlConnection _SC = new SqlConnection("aaaa"))
{
_SC.Open();
}
}
catch (Exception)
{
throw;
}
finally
{
//If connected than
_timer.Stop();
}
}
}

How do I pass an object into a timer event?

Ok so I am using System.Timers.Timer in .Net 4 with C#.
I have my timer object like so:
var timer = new Timer {Interval = 123};
I have my Timer Elapsed event handler pointed at a method like so:
timer.Elapsed += MyElapsedMethod;
And my method looks like this:
static void MyElapsedMethod(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Foo Bar");
}
I want to pass a string into this method, how do I do this?
Thanks
The easiest way to do this is to change the event handler into an anonymous function. It allows you to pass the string at the point of declaration.
string theString = ...;
timer.Elapsed += (sender, e) => MyElapsedMethod(sender, e, theString);
static void MyElapsedMethod(object sender, ElapsedEventArgs e, string theString) {
...
}
If you want to be able to unregister your "Elapsed" event handler again, you shouldn't use a delegate without remembering it in a variable.
So another solution could be to create a custom class based on Timer. Just add whatever members you like and get your custom Timer object back from the "sender" argument of the "Elapsed" event handler:
class CustomTimer : System.Timers.Timer
{
public string Data;
}
private void StartTimer()
{
var timer = new CustomTimer
{
Interval = 3000,
Data = "Foo Bar"
};
timer.Elapsed += timer_Elapsed;
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
string data = ((CustomTimer)sender).Data;
}
This strategy of course works for other events and classes too, as long as the base class is not sealed.
You can save string in some object and read it in event handler:
static string _value;
static void MyElapsedMethod(object sender, ElapsedEventArgs e)
{
Console.WriteLine(_value);
}
UPDATE: same code via different syntax:
timer.Elapsed += (s,e) => Console.WriteLine(_value);
UPDATE: Consider also using System.Threading.Timer instead
State state = new State();
Timer timer = new Timer(OnTimer, state, 0, 123);
state.Value = "FooBar"; // change state object
You can retrieve state in timer callback:
static void OnTimer(object obj)
{
State state = obj as State;
if (state == null)
return;
Console.WriteLine(state.Value);
}
Timer aTimer = new Timer(300);
aTimer.Elapsed += delegate { PublishGPSData(channel, locationViewModel); };
// Hook up the Elapsed event for the timer.
aTimer.AutoReset = true;
aTimer.Enabled = true;
private void PublishGPSData(IModel channel, LocationViewModel locationViewModel)
{
};
Use a field in the same class to hold whatever string you want and then retrieve it in you elapsed event handler. You'll have to be careful about cross-threading issues however.
I wrote this simple class to handle this:
using System;
using System.Timers;
namespace MyProject.Helpers
{
public class MyTimer
{
private volatile Timer _timer = new Timer();
private volatile bool _requestStop = false;
private MyElapsedEventHandler _eventHander;
private MyElapsedEventHandlerWithParam _eventHandlerWithParam;
private object _param;
public MyTimer(int interval, MyElapsedEventHandler elapsedEventHandler, bool autoReset = false)
{
_timer.Interval = interval;
_timer.Elapsed += ElapsedWrapper;
_timer.AutoReset = autoReset;
_eventHander = elapsedEventHandler;
Start();
}
public MyTimer(int interval, MyElapsedEventHandlerWithParam elapsedEventHandler, object param, bool autoReset = false)
{
_timer.Interval = interval;
_timer.Elapsed += ElapsedWrapperWithParam;
_timer.AutoReset = autoReset;
_eventHandlerWithParam = elapsedEventHandler;
_param = param;
Start();
}
private void ElapsedWrapper(object sender, ElapsedEventArgs e)
{
if (!_requestStop && _eventHander != null)
{
_eventHander();
}
}
private void ElapsedWrapperWithParam(object sender, ElapsedEventArgs e)
{
if (!_requestStop && _eventHandlerWithParam != null)
{
_eventHandlerWithParam(_param);
}
}
public void Stop()
{
_requestStop = true;
_timer.Stop();
}
public void Start()
{
_requestStop = false;
_timer.Start();
}
}
public delegate void MyElapsedEventHandlerWithParam(object param);
public delegate void MyElapsedEventHandler();
}
use it like this:
void Main(string[] args){
new MyTimer(durationInSeconds * 1000, EventHandler, "some string");
}
void EventHandler(object param){
doSomethingWithString((string)param);
}
you can also pass the event arguments or any kind of parameters if you edit the delegate (and the call of the event handler in MyTimer class).
Why not just use a Timer and an ElapsedEventHandler?
namespace TimerEventHandler
{
class Program
{
private static Timer myEventTimer;
static void Main(string[] args)
{
// 5 second timer multiply 1000 milliseconds by the time
//e.g. new Timer(60 * 1000 * 10) = 10 minutes
myEventTimer = new Timer(5 * 1000 * 1);
myEventTimer.Enabled = true;
myEventTimer.Elapsed += new ElapsedEventHandler(TimerSchedule_Elapsed);
Console.WriteLine("Timer started!");
// make a thread and wait forever just so console does not go away
Thread.Sleep(Timeout.Infinite);
}
private static void TimerSchedule_Elapsed(object sender, ElapsedEventArgs e)
{
// do something
Console.WriteLine("Timer elapsed!");
}
}
}

Categories