I'm trying to handle the Timer's exception. It would be nice if the class had something like HandlerExceptionEvent so that we could add some event to log something or stop the timer.
PS: I don't want to add a try/catch block inside ElapsedEventHandler().
class Program
{
static void Main(string[] args) {
System.Timers.Timer t = new System.Timers.Timer(1000);
t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
t.Start();
System.Threading.Thread.Sleep(10000);
t.Stop();
Console.WriteLine("\nDone.");
Console.ReadLine();
}
static void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
Console.WriteLine("Ping!");
throw new Exception("Error!");
}
}
PS: I don't want to add "try/catch Exception" inside ElapsedEventHandler()
Since the Timer class doesn't support such an event how would you otherwise catch an exception?
If you insist on using the Timer class then perhaps this is your only option:
var t = new System.Timers.Timer(1000);
t.Elapsed += (sender, e) => {
try
{
t_Elapsed(sender, e);
}
catch (Exception ex)
{
// Error handling here...
}
};
This way the actual handler t_Elapsed doesn't contain any error handling and you can create a wrapper class for the Timer class that hides this implementation detail and in turn provides an event for exception handling.
Here's one way to do that:
class ExceptionHandlingTimer
{
public event Action<Exception> Error;
System.Timers.Timer t;
public ExceptionHandlingTimer(double interval)
{
t = new System.Timers.Timer(interval);
}
public void Start()
{
t.Start();
}
public void AddElapsedEventHandler(ElapsedEventHandler handler)
{
t.Elapsed += (sender, e) =>
{
try
{
handler(sender, e);
}
catch (Exception ex)
{
if (Error != null)
{
Error(ex);
}
else
{
throw;
}
}
};
}
}
Related
In my web socket wcf service I'm using timer elapsed event to do some logic on my object and after that send information to client (by callback object). I also track callback closed event to clean all object that I'm using in timer elapsed event handler. The problem that i occured is that, when I'm trying to dispose my object i get errors that is still working and to prevent that i try to use lock in both code (timer elapsed event and closed channel event) but it not working correctly (i'm still getting errors that i'm calling method on my object that is no allowed for this moment - this mean that timer elapsed and also call it in the same time).
Is WCF do something special which causes to lock don't work as I expected ?
Here is some of my code:
[ServiceContract(CallbackContract = typeof(IWebSocketsCallback))]
public interface IWebSockets
{
[OperationContract(IsOneWay = true, Action = "*")]
void Start(Message msg);
}
[ServiceContract]
public interface IWebSocketsCallback
{
[OperationContract(IsOneWay = true, Action = "*")]
void SendToClient(Message msg);
}
public class WebSockets : IWebSockets
{
private IWebSocketsCallback callback;
private bool handlePIChanges = false;
private PIDataPipe pipe;
private PIEventsProducer piEventsProducer;
private Timer timer;
private readonly object timerLock = new object();
private readonly object pipeLock = new object();
private bool isPipeClosed = false;
public WebSockets()
{
callback = OperationContext.Current.GetCallbackChannel<IWebSocketsCallback>();
((IChannel)callback).Closed += WebSockets_Closed;
}
public void Start(Message msg)
{
// some custom logic that i ommited ...
timer = CreateTimer();
timer.Elapsed += (sender, e) => PIQueryingCallback(pipe, timer);
}
private void WebSockets_Closed(object sender, EventArgs e)
{
lock (timerLock)
{
handlePIChanges = false;
if (timer != null)
{
timer.Stop();
timer.Dispose();
piEventsProducer.Clear();
}
}
lock (pipeLock)
{
if (pipe != null)
{
pipe.RemoveSignups(pipe.AsReadOnly()); // this cause error, because GetObserverEvents not stopped working
pipe.Close();
isPipeClosed = true;
}
}
}
private void PIQueryingCallback(PIDataPipe pipe, Timer myTimer)
{
bool moreIndicator;
AFErrors<PIPoint> errors;
lock (pipeLock)
{
do
{
if (handlePIChanges && !isPipeClosed)
{
try
{
errors = pipe.GetObserverEvents(2000, out moreIndicator); // this method calls make block for other call on this object untill it return results
}
catch (Exception e)
{
moreIndicator = false;
continue;
}
}
else
{
moreIndicator = false;
}
}
while (moreIndicator);
}
if (handlePIChanges)
{
lock (timerLock)
{
if (handlePIChanges)
{
myTimer.Start();
}
}
}
}
// this method is called after GetObserveEventsCompleted
private void HandlePIDataEventProducerChanges(string msg)
{
if (handlePIChanges && !isPipeClosed)
{
if (((IChannel)callback).State == CommunicationState.Opened)
{
try
{
callback?.SendPIDataChangesToClient(CreateMessage(msg));
}
catch (Exception ex)
{
}
}
}
}
}
I'm following on with a tutorial detailing handling events thrown in multiple subscribers to an event. However when the code is run, the TargetInvocationException catch block isn't catching the exceptions thrown in the method body of the subscribers: throw new Exception("Hello") and throw new Exception("World") respectively.
Instead I get an unhandled exception error in the first listener, predictably at throw new Exception("Hello") in private static void AlarmListener.
What is it that I'm doing incorrectly when attempting to catch the invoked method's exceptions?
class AggregatingExceptions
{
public void Main()
{
//create the alarm
AlarmAndLocation alarm = new AlarmAndLocation();
//subscribe the listeners
alarm.OnAlarmRaised += AlarmListener;
alarm.OnAlarmRaised += AlarmListener2;
try
{
alarm.RaiseAlarm("Kitchen");
}
catch (AggregateException agg)
{
foreach (Exception ex in agg.InnerExceptions)
{
Console.WriteLine(ex.Message);
}
}
}
private static void AlarmListener(object sender, AlarmEventArgs e)
{
Console.WriteLine("Alarm listener 1 called.");
throw new Exception("Hello");
}
private static void AlarmListener2(object sender, AlarmEventArgs e)
{
Console.WriteLine("Alarm listener 2 called.");
throw new Exception("World");
}
}
public class AlarmAndLocation
{
public event EventHandler<AlarmEventArgs> OnAlarmRaised = delegate { };
public List<Exception> exceptionList = new List<Exception>();
public void RaiseAlarm(string location)
{
foreach (Delegate handler in OnAlarmRaised.GetInvocationList())
{
try
{
handler.DynamicInvoke(this, new AlarmEventArgs(location));
}
catch (TargetInvocationException ex)
{
exceptionList.Add(ex.InnerException);
}
}
if(exceptionList.Count > 0)
{
throw new AggregateException(exceptionList);
}
}
}
public class AlarmEventArgs : EventArgs
{
public string Location { get; set; }
public AlarmEventArgs(string location)
{
Location = location;
}
}
I am having a case where an exception thrown in UI thread doesn't get catched in the calling thread.
using System;
using System.Diagnostics;
using System.Threading;
using System.Windows;
namespace SynchronisationContextAndExceptionWPF
{
public partial class MainWindow : Window
{
private readonly SynchronizationContext _synchronizationContext;
public MainWindow()
{
InitializeComponent();
_synchronizationContext = SynchronizationContext.Current;
}
private void Button_OnClick(object sender, RoutedEventArgs e)
{
try
{
_synchronizationContext.Send(
x =>
{
try
{
DoSomethingOnUiThreadThatThrowsException();
}
catch (Exception)
{
Debug.WriteLine("Catched Exception in thread that threw it.");
throw;
}
}, null);
}
catch (Exception)
{
Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
throw;
}
}
private static void DoSomethingOnUiThreadThatThrowsException()
{
throw new Exception("Any Exception...");
}
}
}
First I thought that cannot possible (all documentation I found said that I can catch exceptions there).
After some reasearch I found the problem: My application uses an UnhandledExceptionHandler. That handles the DispatcherUnhandledException-Event. I am showing some information to the user and set e.Handled = true;:
using System.Diagnostics;
using System.Windows;
using System.Windows.Threading;
namespace SynchronisationContextAndExceptionWPF
{
public partial class App : Application
{
public App()
{
DispatcherUnhandledException += App_DispatcherUnhandledException;
}
private static void App_DispatcherUnhandledException(
object sender,
DispatcherUnhandledExceptionEventArgs e)
{
Debug.WriteLine("Catched Exception in UnhandledExceptionHandler.");
// This line makes the difference:
e.Handled = true;
}
}
}
So the question: why is the DispatcherUnhandledException-Event raised even if I handle it?
How would you solve this situation?
If you have a lot of controls, you can generate a new class which remenbers the special exception variable. So you only need to change the initialization of your _synchronizationContext (hopefully only once at your base class of your controls).
public partial class MainWindow : Window
{
private readonly MySynchronizationContext _synchronizationContext;
public MainWindow()
{
InitializeComponent();
_synchronizationContext = new MySynchronizationContext(SynchronizationContext.Current);
}
private void button_Click(object sender, RoutedEventArgs e)
{
try
{
_synchronizationContext.Send(
x =>
{
DoSomethingOnUiThreadThatThrowsException();
}, null);
}
catch (Exception)
{
Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
throw;
}
}
private static void DoSomethingOnUiThreadThatThrowsException()
{
throw new Exception("Any Exception...");
}
}
class MySynchronizationContext
{
SynchronizationContext innerContext;
public MySynchronizationContext(SynchronizationContext ctx)
{
innerContext = ctx;
}
public virtual void Send(SendOrPostCallback d, object state)
{
Exception threadException = null;
try
{
innerContext.Send(_ =>
{
try
{
d.Invoke(state);
}
catch (Exception exception)
{
threadException = exception;
}
}, null);
}
catch (Exception ex)
{
}
if (threadException != null)
{
throw new Exception("Synchronization error", threadException);
}
}
}
Inside your lambda expression you can set an Exception variable and check this variable later at the calling thread. If it was set, then throw exception at calling thread.
private void button_Click(object sender, RoutedEventArgs e)
{
Exception threadException = null;
try
{
_synchronizationContext.Send(
x =>
{
try
{
DoSomethingOnUiThreadThatThrowsException();
}
catch (Exception ex)
{
Debug.WriteLine("Catched Exception in thread that threw it.");
threadException = ex;
//throw; --> don't throw exception here; otherwise you will get DispatcherUnhandledException twice.
}
}, null);
}
catch (Exception)
{
Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
throw;
}
if(threadException != null)
{
Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
throw threadException; //throw you previously catched exception here.
}
}
Kind Regards,
Daniel
I have this code below:
using System;
using System.Windows.Forms;
namespace MyCode
{
public partial class Main_GUI : Form
{
//Attributes
private Processes process;
//Constructor
public Main_GUI()
{
InitializeComponent(); //a form with a button named BUTTON_Start, and a label named LABEL_log
p = new Processes();
}
//OnClickStart
private void BUTTON_Start_Click(object sender, EventArgs e)
{
try
{
LABEL_log.Text = "Started...";
p.start();
}
catch (Exception ex)
{
//do something with the exception
}
}
}//End of Class
public class Processes
{
//Constructor
public Processes() { }
//Methods
public void start()
{
try
{
//Do something
//...
//when finished send an event the Main_GUI Class (Form) in order to change the LABEL_log.Text value to "finished !"
}
catch (Exception e)
{
//do something with the exception
}
}
}
}
I ve tried a lot to create some events, I even use this example :
http://www.codeproject.com/Articles/11541/The-Simplest-C-Events-Example-Imaginable
but I cant understant how to create an event with my classes...
I such a fool I know but I really need your help !
Thanks the team !!
Regards.
FB
Define the event in the Process class:
public event EventHandler Finished;
Then in the same class define a method that raises the event "safely":
protected void RaiseFinished()
{
// Make sure the event has at least one subscriber.
if(Finished != null)
{
Finished(this, EventArgs.Empty);
}
}
You call the method where you want your event to be raised, in your case the start method:
public void Start()
{
try
{
//Do something
//...
RaiseFinished();
}
catch (Exception e)
{
//do something with the exception
}
}
Then in your Main_GUI class constructor subscribe to the event defining an handler:
//Constructor
public Main_GUI()
{
InitializeComponent(); //a form with a button named BUTTON_Start, and a label named LABEL_log
p = new Processes();
// Subscribe to the event.
p.Finished += p_Finished;
}
// This will get called when the Finished event is raised.
private void p_Finished(object sender, EventArgs e)
{
LABEL_log.Text = "Finished!";
}
What is the proper way to create and dispose a system timer my code is as below
using System.Timers;
public void StartGetFileTimer(int interval)
{
if (TIMER_GET_FILE != null)
{
StopGetFileTimer();
}
try
{
if (TIMER_GET_FILE == null)
{
TIMER_GET_FILE = new Timer();
TIMER_GET_FILE.Interval = interval * 1000;
TIMER_GET_FILE.Elapsed += new ElapsedEventHandler(GetLatestFileTimer_tick);
TIMER_GET_LATEST_FILE.Enabled = true;
TIMER_GET_FILE.Start();
}
else
{
//log
}
}
catch (Exception e)
{
//log
}
}
public void StopGetFileTimer()
{
try
{
if (TIMER_GET_LATEST_FILE != null)
{
TIMER_GET_LATEST_FILE.Elapsed -= new ElapsedEventHandler(GetLatestFileTimer_tick);
TIMER_GET_LATEST_FILE.Stop();
TIMER_GET_LATEST_FILE.Enabled = false;
TIMER_GET_LATEST_FILE.Dispose();
TIMER_GET_LATEST_FILE = null;
}
}
catch (Exception ex)
{
//log
}
}
Simply use the Dispose method, but as the documentation says:
Callbacks can occur after the Dispose() method overload has been
called, because the timer queues callbacks for execution by thread
pool threads. You can use the Dispose(WaitHandle) method overload to
wait until all callbacks have completed.
The Dispose(WaitHandle) should be used like:
ManualResetEvent resetEvent = new ManualResetEvent(false);
Timer.Dispose(resetEvent);
resetEvent.WaitOne();