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();
}
}
}
Related
My service is running but it does not do any of the logic i inserted in OnStart,
Also, I am try to log messages to the eventviewer but it does not even get to that part (which i assume is falling before the OnStart..)
Can someone please tell me what i am doing wrong? Thanks,
public partial class DSGService : ServiceBase
{
private static string ftpPath = ConfigurationManager.AppSettings["FtpPath"];
private Timer _timer;
private bool _isRunning;
public DSGService()
{
InitializeComponent();
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
WriteToEventViewer("error!:" + e.ExceptionObject.ToString());
}
OnStart logic
protected override void OnStart(string[] args)
{
_isRunning = false;
_timer = new Timer
{
AutoReset = true,
Interval = 5000,
};
_timer.Elapsed += new ElapsedEventHandler(this.TimerElapsed);
_timer.Start();
}
code to do things
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
if (_isRunning)
{
WriteToEventViewer("isrunning is true");
return;
}
try
{
_isRunning = true;
WriteToEventViewer("started");
//do things..
WriteToEventViewer("generated!");
}
}
finally
{
_isRunning = false;
WriteToEventViewer("done");
}
}
private void GenerateAndPublishData(ServerData server)
{
try
{
//do things...
}
catch (Exception ee)
{
WriteToEventViewer(string.Format("error: {0}", ee);
}
}
protected override void OnStop()
{
_timer.Stop();
_timer.Dispose();
_timer = null;
}
write to eventviewer
private void WriteToEventViewer(string msg)
{
using (EventLog eventLog = new EventLog("DSGService"))
{
eventLog.Source = "DSGService";
eventLog.WriteEntry(msg, EventLogEntryType.Information, 101, 1);
}
}
}```
This is probably the result of an exception inside the TimerElapsed method, that prevents the timer from restarting. To aviod this, here's what you do:
Set the AutoReset property of your timer to false.
Inside the TimerElapsed event handler, in the finally clause, start the timer again.
This means that even if an exception occured in your TimerElapsed event handler, the timer will start again.
I have to test a boolean every 250ms, max 2 seconds, and stop when it's true.
Tried this, but Thread.Sleep isn't a good solution for me because it's freezing my software, and waiting for even more won't change anything because the boolean won't change while it's frozen.
bool onLine = false;
Stopwatch chrono = new Stopwatch();
chrono.Start();
while (chrono.ElapsedMilliseconds < 2000)
{
if (!State().Equals(Online))
{
System.Threading.Thread.Sleep(250);
}
else
{
onLine = true;
operationCompleted();
break;
}
}
if (!onLine)
{
MessageBox.Show("Error");
}
I don't know how to make the tests in an event raised by a timer if someone has a correct implementation?
The currently accepted answer is not a particularly good use of the async await paradigm, and introduces a lot of noise for something that need not be complicated. Simply scheduling synchronous, blocking code onto the ThreadPool with Task.Run rather than upgrading to fully async code is a half-measure.
Rewriting that code without the blocking code and the spurious Task.Run, it could be as simple as:
private async void button1_Click(object sender, EventArgs e)
{
bool onLine = false;
Stopwatch chrono = new Stopwatch();
chrono.Start();
while (chrono.ElapsedMilliseconds < 2000)
{
if (!State().Equals(Online))
{
await Task.Delay(250);
}
else
{
onLine = true;
break;
}
}
if (onLine)
{
operationCompleted();
}
else
{
MessageBox.Show("Error");
}
}
Not sure what it looks like in WPF, but here is how it would be done in WinForms. Note that the button handler has been marked with async:
private async void button1_Click(object sender, EventArgs e)
{
bool onLine = false;
Stopwatch chrono = new Stopwatch();
await (Task.Run(new Action(() =>
{
chrono.Start();
while (chrono.ElapsedMilliseconds < 2000)
{
if (!State().Equals(Online))
{
System.Threading.Thread.Sleep(250);
}
else
{
onLine = true;
break;
}
}
})));
if (onLine)
{
operationCompleted();
}
else
{
MessageBox.Show("Error");
}
}
Here's an example using a threading timer:
public class Foo
{
public System.Threading.Timer EventTimer
{
get;
set;
}
public long TimingInterval
{
get;
set;
}
public Foo()
{
EventTimer = new System.Threading.Timer(new TimerCallback(Foo.DoCheck),
this,
this.TimingInterval,
this.TimingInterval);
}
public void DoCheck()
{
//do check here
}
Here's one way this could be accomplished with a timer. The idea is to set the interval to how often you want to check, and set a timeout variable to the time you want to stop checking. Then, in the Tick event (which triggers every interval), do your online check, followed by a check of the timeout.
[Updated for WPF to use a DispatcherTimer]
System.Windows.Threading.DispatcherTimer timer = new DispatcherTimer();
private DateTime timeout;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
timeout = DateTime.Now.AddSeconds(2);
timer.Tick += Timer_Tick;
timer.Interval = TimeSpan.FromMilliseconds(250);
timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
if (State().Equals(Online))
{
onLine = true;
operationCompleted();
timer.Stop();
}
if (DateTime.Now > timeout)
{
timer.Stop();
MessageBox.Show("Error");
}
}
// rest of code omitted
You can use a BackgroundWorker.
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += bw_DoWork;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
The DoWork event handler of a BackgroundWorker is executed on a deditecated thread, so your software will not freeze.
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
bool onLine = false;
Stopwatch chrono = new Stopwatch();
chrono.Start();
while (chrono.ElapsedMilliseconds < 2000)
{
if (!State().Equals(Online))
{
System.Threading.Thread.Sleep(250);
}
else
{
onLine = true;
break;
}
}
e.Result = onLine;
}
When the background operation has completed, the RunWorkerCompleted event occurs. You can pass an object from DoWork to RunWorkerCompleted by using
e.Result.
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
bool onLine = (bool)e.Result;
if (onLine)
{
operationCompleted();
}
else
{
MessageBox.Show("Error");
}
}
DoWork occurs when RunWorkerAsync is called. You have to call bw.RunWorkerAsync(); to start your BackgroundWorker.
I do have one checking function that will run once opening the application.
How to make it Auto Function like every 20 seconds run the function?
Main()
{
Checking();
}
public void Checking() // run this function every 20 seconds
{ // some code here
}
You can use the C# Timer class
public void Main()
{
var myTimer = new Timer(20000);
myTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
myTimer.Enabled = true;
Console.ReadLine();
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
Main()
{
Timer tm = new Timer();
tm.Interval = 20000;//Milliseconds
tm.Tick += new EventHandler(tm_Tick);
tm.Start();
}
void tm_Tick(object sender, EventArgs e)
{
Checking();
}
public void Checking()
{
// Your code
}
I wrote a windows service to call my class library every 10 mins interval,it works fine when start or restart .once the job done it suppose to re run again every 10 min's that's not happening at all.Am not sure what am missing,some one please identify the correct way.
Here is my code
public partial class Service1 : ServiceBase
{
private Timer _timer;
private DateTime _lastRun = DateTime.Now;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
log4net.Config.XmlConfigurator.Configure();
_timer = new Timer(10 * 60 * 1000); // every 10 minutes
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
Shell Distribute= new Shell();
Distribute.Distribute();
}
protected override void OnStop()
{
this.ExitCode = 0;
base.OnStop();
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//if (_lastRun.Date < DateTime.Now.Date)
//{
_timer.Stop();
_lastRun = DateTime.Now;
_timer.Start();
//}
}
}
}
Your problem is compare of date if (_lastRun.Date < DateTime.Now.Date) so your code runs once a day.
I agree with Ozgur. It appears that your logic is wrong. You can just stop the timer during the timer_Elapsed event do you logic and restart timers
Something like :
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
try{
// stop the timer while we are running the cleanup task
_timer.Stop();
//
// do cleanup stuff
//
}catch (Exception e){
//do your error handling here.
}
finally{
_timer.Start();
}
}
}
Just wrap it with a try catch and finally so you handle exceptions and can make sure the timer is started again. Also please review this link Best Timer for using in a Windows service
Okie Finally i got the answer,why its not working (One of the expert from other forum point out my mistake)
This the code works well based on timer interval.
public partial class Service1 : ServiceBase
{
private Timer _timer;
private DateTime _lastRun = DateTime.Now;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
log4net.Config.XmlConfigurator.Configure();
_timer = new Timer(10 * 60 * 1000); // every 10 minutes
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
Shell Distribute= new Shell();
Distribute.Distribute();
_timer.start();//this line was missed in my original code
}
protected override void OnStop()
{
this.ExitCode = 0;
base.OnStop();
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//if (_lastRun.Date < DateTime.Now.Date)
//{
try
{
_timer.Stop();
Shell Distribute= new Shell();
Distribute.Distribute();
}
catch(exception ex)
{}
finally
{
_timer.Start();
}
//}
}
}
}
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!");
}
}
}