I have this piece of code, I'm using a timer to call my RunTest() function. If I don't use timer, all the unhandled exception inside RunTest() are caught, but with this timer code they are not getting caught. What mistake am I making?
private static TelemetryClient telemetryClient = new TelemetryClient();
private static System.Timers.Timer aTimer;
static void Main(string[] args)
{
// Register Unhandled Exception Handler
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
// Set the Instrumentation Key to track the WebJob Exception
TelemetryConfiguration.Active.InstrumentationKey = SecureConfigReader.GetSetting("ApplicationInsightsKey");
Configure();
if (args.Length > 0)
{
// Create a timer with a ten second interval.
aTimer = new System.Timers.Timer(10000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
double Scheduled_Interval = Convert.ToDouble(args[0]);
// Set the Interval to 300 seconds.
aTimer.Interval = TimeSpan.FromSeconds(Scheduled_Interval).TotalMilliseconds;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
}
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
RunTests();
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
ExceptionTelemetry excTelemetry = new ExceptionTelemetry((Exception)e.ExceptionObject);
excTelemetry.SeverityLevel = SeverityLevel.Critical;
excTelemetry.HandledAt = ExceptionHandledAt.Unhandled;
telemetryClient.InstrumentationKey = SecureConfigReader.GetSetting("ApplicationInsightsKey");
telemetryClient.TrackException(excTelemetry);
//make sure all telemetry is sent before closing the app
telemetryClient.Flush();
}
/*
* 1. Find all tests
* 2. Run all tests, collecting all results
* 3. Process alerts if any
* 4. Save results
*/
private static void RunTests()
{
List<SyntheticTransactionTableEntity> results = new List<SyntheticTransactionTableEntity>();
List<ISyntheticTransaction> tests = new List<ISyntheticTransaction>();
}
Its documented that:
The Timer component catches and suppresses all exceptions thrown by
event handlers for the Elapsed event.
You need to catch within the OnTimedEvent method and then propagate that exception back out e.g by throwing it on another thread if you want CurrentDomain_UnhandledException to catch it (throw in ThreadPool.QueueUserWorkItem())
Alternatively create a handler:
private static void TimerExceptionHandler(Exception ex)
{
Console.WriteLine(ex.ToString());
...
}
Pass it to the ElapsedEventHandler:
aTimer.Elapsed += (sender, e) => { OnTimedEvent(sender, e, TimerExceptionHandler); };
Call it when an exception is thrown:
private static void OnTimedEvent(object source, ElapsedEventArgs e, Action<Exception> timerExceptionHandler)
try
{
RunTests();
}
catch (Exception ex)
{
timerExceptionHandler(ex);
}
Related
When I add a COM reference in Visual Studio, this method works, but not with
Activator.CreateInstance(TypeZVT) or CreateOleObject in Delphi ...
Delphi:
VarObj := CreateOleObject( 'Portalum_Zvt.ZVT' );
VarObj.BetragSenden('1,22'); //Throws errors.
C# DLL:
private async void OnTimedEvent(Object source, ElapsedEventArgs e)
{
await PaymentAsync((decimal)Betrag);
}
public double Betrag;
public void BetragSenden(double Betrag)
{
this.Betrag = Betrag;
System.Timers.Timer t = new System.Timers.Timer(1000);
t.AutoReset = false;
t.Elapsed += new ElapsedEventHandler(OnTimedEvent);
t.Start();
}
I have a timer using which i am calling a method - {OnElapsedTime} And this should responsible for database access and updation for every interval of time.
protected override void OnStart(string[] args)
{
try
{
ServiceLogFile("Service is started at " + DateTime.Now);
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = Int32.Parse(ConfigurationManager.AppSettings["tracktime"]); //number in miliseconds
timer.Enabled = true;
}
catch(Exception ex)
{
ServiceLogFile("Error in {OnStart} :" + ex.ToString());
}
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
try
{
ServiceLogFile("Check for Database values - " + DateTime.Now);
th = new Thread(new ThreadStart(Autocancellation));
int ThreadID = Thread.CurrentThread.ManagedThreadId;
ServiceLogFile("Thread ID = " + ThreadID);
th.Start();
}
catch (Exception ex)
{
ServiceLogFile("Error in {OnElapsedTime} :" + ex.ToString());
}
}
public void Autocancellation()
{
try
{
lock (this)
{
//connection to database
//select Query and update
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message());
}
}
If we can see the above code - I am creating a new thread for every OnElapsedTime call.
Please help me with creating a single thread outside of this method or anywhere and using the same instance inside {OnElapsedTime} whenever this method is being called (In my case - 5 seconds)
Assuming
that we properly implement cooperative cancellation (otherwise there are no reliable ways to stop the currently running job)
And we are not forced to use threads - https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/task-parallel-library-tpl
And we are not required to run exactly once per 5 seconds (to accommodate the cooperative cancellation from bullet 1) - C# Timer elapsed one instance at a time
the simplest (or rather the simplest without any additional libraries) way would be to use Task, TaskCancellationSource and a timer with AutoReset = false
public class Service
{
private Task _job;
private CancellationTokenSource _cancellationTokenSource;
private readonly System.Timers.Timer _timer;
public Service()
{
_timer = new System.Timers.Timer();
{
_timer.AutoReset = false;
_timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
_timer.Elapsed += OnElapsedTime;
}
}
public void Start()
{
Console.WriteLine("Starting service");
_timer.Start();
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
Console.WriteLine("OnElapsedTime");
if (_job != null)
{
CancelAndWaitForPreviousJob();
}
Console.WriteLine("Starting new job");
_cancellationTokenSource = new CancellationTokenSource();
_job = Task.Run(
() => ExecuteJob(_cancellationTokenSource.Token),
_cancellationTokenSource.Token);
_timer.Start();
}
private void CancelAndWaitForPreviousJob()
{
_cancellationTokenSource.Cancel();
try
{
Console.WriteLine("Waiting for job to complete");
_job.Wait(
millisecondsTimeout: 5000); // Add additional timeout handling?
}
catch (OperationCanceledException canceledExc)
{
Console.WriteLine($"Cancelled the execution: {canceledExc}");
}
catch (Exception exc)
{
Console.WriteLine($"Some unexpected exception occurred - ignoring: {exc}");
}
}
private void ExecuteJob(CancellationToken cancellationToken)
{
Console.WriteLine("ExecuteJob start");
try
{
for (var i = 0; i < 10; i++)
{
Console.WriteLine($"Job loop Iteration {i}");
if (cancellationToken.IsCancellationRequested)
{
Console.WriteLine("Cancellation requested - ending ExecuteJob");
return;
}
Thread.Sleep(1000);
}
}
finally
{
Console.WriteLine("ExecuteJob end");
}
}
}
While it is a working solution you may be interested in Quartz.net - it has only a moderate learning curve and it is designed exactly for such scenarios.
P.S.: Also it seems that your application is a service based on https://learn.microsoft.com/en-Us/dotnet/api/system.serviceprocess.servicebase?view=netframework-4.8. In such a case you may be interested in topshelf - it greatly simplifies a lot of things related to services.
I want to catch all unhandled exceptions in my application. so I used this code to catch all the unhandled exceptions:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
SaveEx(e.Exception);
Application.Exit();
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
SaveEx((Exception)e.ExceptionObject);
Application.Exit();
}
static void SaveEx(Exception ex)
{
bool exists = System.IO.Directory.Exists(Path.GetDirectoryName(#"C:\AppLogs\"));
if (!exists)
System.IO.Directory.CreateDirectory(Path.GetDirectoryName(#"C:\AppLogs\"));
String filePath = #"C:\AppLogs\" + DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss") + ".txt";
String log = "===========Start=============\r\n";
log += "Error Message: " + ex.Message + "\r\n";
log += "Stack Trace: " + ex.StackTrace + "\r\n";
log += "===========End=============";
System.IO.File.WriteAllText(filePath, log);
}
}
I tried to raise these exceptions with a divide in 0:
on main thread it's work perfect:
int t = 0;
int r = 5 / t;
But when i try to do it inside a Thread:
Thread thread = new Thread(delegate()
{
int t = 0;
int r = 5 / t;
});
thread.Start();
The CurrentDomain_UnhandledException function got called but it keeps calling the int r = 5 / t; row in my code so I have a loop of exceptions. Any idea what can be the problem? the thread is called only once.
You need to change Application UnhandledExceptionMode
to UnhandledExceptionMode.CatchException to make things works correctly. Microsoft already wrote a very good article about it here.
I tried to simulate your work. Everything worked well, take a look on my example.
[STAThread]
static void Main()
{
// Set the unhandled exception mode to force all Windows Forms errors to go through
// our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += Application_ThreadException;
// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "Application_ThreadException");
Application.Exit();
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
MessageBox.Show(exception.Message, "CurrentDomain_UnhandledException");
Application.Exit();
}
So, if we raise an exception inside a thread like below:
private void button1_Click(object sender, EventArgs e)
{
var thread = new Thread(delegate () {
throw new DivideByZeroException();
});
thread.Start();
}
button1_Click is fired.
thread get started and raises a DividedByZeroException.
CurrentDomain_UnhandledException catches the exception, shows the message and closes the app
I am using a websocket sharp dll in my windows application to get messages from a GDAX server. Everything is working fine so far - the messages are coming and i am processing them. The point where I am stuck is when the messages stops coming. At least I don't find anything in the WebSocket.OnMessage Event(https://github.com/sta/websocket-sharp) that can help me in tracking when the messages are stopped (I tried emitonping also)
Now the messages I received have a message type 'Heartbeat' which is sent every second. I want to add a separate timer control to check if the heartbeat messages are coming every second or not and if it stops coming then I will need to reconnect the server again. But since nothing happens when the messages stops coming how do i track it, where should I put the timer code to check when heartbeat messages stops coming?
I hope I could explain the situation wherein I am struck. If someone is eager to help me and needs more inputs please let me know.
Update
private void _3_Load(object sender, EventArgs e)
{
ConnectAndGetWebsocketFeedMessages();
}
public delegate void WSOpen(string text);
public delegate void WSMessage(string message);
public delegate void WSError(string text);
public delegate void WSClose(string text);
private static string _endPoint = "wss://ws-feed.gdax.com";
WebSocket ws = new WebSocket(_endPoint);
private bool IsConnected { get; set; }
private string ProductId { get; set; }
string productId = "LTC-EUR";
ConcurrentQueue<string> concurrentQueue = new ConcurrentQueue<string>();
public void SetWebSocketSharpEvents()
{
ws.Log.Level = LogLevel.Trace;
ws.OnOpen += (sender, e) =>
{
IsConnected = true;
OnWSOpen("Connection Status :: Connected *********");
};
ws.EmitOnPing = true;
ws.OnMessage += (sender, e) =>
{
if (e.IsPing)
{
OnWSMessage("ping received");
}
else
{
OnWSMessage(e.Data);
}
};
ws.OnError += (sender, e) =>
{
IsConnected = false;
OnWSError(e.Message); //An exception has occurred during an OnMessage event. An error has occurred in closing the connection.
if (ws.IsAlive)
ws.Close();
};
ws.OnClose += (sender, e) =>
{
IsConnected = false;
OnWSClose("Close");
};
ws.ConnectAsync();
}
private void ConnectAndGetWebsocketFeedMessages()
{
SetWebSocketSharpEvents();
}
private void SubscribeProduct(string sProductID)
{
if (IsConnected)
{
ProductId = sProductID;
string data = "{\"type\": \"subscribe\", \"product_ids\": [\"" + sProductID + "\"]}";
ws.Send(data);
ws.Send("{\"type\": \"heartbeat\", \"on\": true}");
}
}
void OnWSOpen(string text)
{
SubscribeProduct(productId);
timer1.Interval = 1000;
timer1.Tick += timer1_Tick;
timer1.Start();
}
DateTime lastHeartbeatTime = DateTime.MinValue;
bool isTimerStart = false;
void OnWSMessage(string message)
{
concurrentQueue.Enqueue(message);
SaveHeartbeatMessageTime(message);
ProcessMessage(message);
}
private void SaveHeartbeatMessageTime(string jsonString)
{
var jToken = JToken.Parse(jsonString);
var typeToken = jToken["type"];
var type = typeToken.ToString();
if (type == "heartbeat")
{
lastHeartbeatTime = DateTime.Now;
this.Invoke(new MethodInvoker(delegate()
{
lbllastheartbeat.Text = lastHeartbeatTime.ToLongTimeString();
}));
}
}
private void ProcessMessage(string message) { }
void OnWSError(string text) { }
void OnWSClose(string text) { }
bool isMessagesReceived = false;
private void timer1_Tick(object sender, EventArgs e) // it stops working as soon as lbllastheartbeat gets some value
{
DateTime currentTime = DateTime.Now;
TimeSpan duration = currentTime.Subtract(lastHeartbeatTime);
this.Invoke(new MethodInvoker(delegate()
{
lblNow.Text = currentTime.ToLongTimeString();
}));
if (Int16.Parse(duration.ToString("ss")) > 1)
{
// reconnect here
}
}
Edit
I am using windows form timer control and it keeps on calling timer1_Tick method and does not call OnWSMessage method. How do I ensure that both run parallel and if any message is missed or the message stops coming then it reconnects?
Edit2
The solutions provided below suggests to add the timer functionality in onMessage event but what will happen if I do not receive messages? If the messages are not received then the code does not do anything. I have taken a global variable and whenever a message comes it adds the time in that variable. Now I want to run a separate timer control which will check whether there is anything in that variable and if its value i.e difference of seconds is more than 1 then do something else keep on checking.
Is there anyone who can look into this and advise please.
Update2: I still want to do this with windows.timer control and not threading.timer. I have taken two labels in my windows app, lbllastheartbeat (to show the time when heartbeat message is received) and lblNow (to show the current time when timer is called).
Requirement - My timer will check if any heartbeat message is missed and that is done through the 'lastHeartbeatTime' variable which stores the time when the heartbeat message is received.
I would appreciate if anyone can review my code and suggest what or where I am doing wrong.
The answer has already been given - you need to start timer which will fire after your timeout period when you receive message, and reset that timer every time you receive message. But it seems you want code example, so here it is (with comments):
System.Threading.Timer _timeoutTimer;
private readonly object _timeoutTimerLock = new object();
private void ResetTimeoutTimer() {
// if you are sure you will never access this from multiple threads at the same time - remove lock
lock (_timeoutTimerLock) {
// initialize or reset the timer to fire once, after 2 seconds
if (_timeoutTimer == null)
_timeoutTimer = new System.Threading.Timer(ReconnectAfterTimeout, null, TimeSpan.FromSeconds(2), Timeout.InfiniteTimeSpan);
else
_timeoutTimer.Change(TimeSpan.FromSeconds(2), Timeout.InfiniteTimeSpan);
}
}
private void StopTimeoutTimer() {
// if you are sure you will never access this from multiple threads at the same time - remove lock
lock (_timeoutTimerLock) {
if (_timeoutTimer != null)
_timeoutTimer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
}
}
private void ReconnectAfterTimeout(object state) {
// reconnect here
}
public void SetWebSocketSharpEvents() {
ws.Log.Level = LogLevel.Trace;
ws.OnOpen += (sender, e) => {
// start timer here so that if you don't get first message after 2 seconds - reconnect
ResetTimeoutTimer();
IsConnected = true;
OnWSOpen("Connection Status :: Connected *********");
};
ws.EmitOnPing = true;
ws.OnMessage += (sender, e) => {
// and here
ResetTimeoutTimer();
if (e.IsPing) {
OnWSMessage("ping received");
}
else {
OnWSMessage(e.Data);
}
};
ws.OnError += (sender, e) => {
// stop it here
StopTimeoutTimer();
IsConnected = false;
OnWSError(e.Message); //An exception has occurred during an OnMessage event. An error has occurred in closing the connection.
if (ws.IsAlive)
ws.Close();
};
ws.OnClose += (sender, e) => {
// and here
StopTimeoutTimer();
IsConnected = false;
OnWSClose("Close");
};
ws.ConnectAsync();
}
from your question what i understand is , your message is sending after every seconds , but the problem is only when it stop you want to know and run it again, if it like that , you just apply timer and check for every seconds if the message not sent after a second or more (check sentMessage() Method set a boolean if message sent it should give true otherwise false) , than give the command to reconnect the server again .
I'm implementing a Client who can ask a service for a certain action and also an abort button for this action.
Once I run the action using background thread the abort button should become active, but instead the entire GUI is stuck with the mouse icon as hour glass (Should mention that the action is still indeed occurring).
private void actionButton_Click(object sender, EventArgs e)
{
Run(RunMode.Action);
}
private void Run(RunMode runMode)
{
abortButton.Enabled = true;
try
{
var name = "ds_file";
var url = UrlProvider.BuildRequestUrl(runMode, name);
StartLoading($"Running request: {url}");
RunWorker(url);
}
catch (Exception ex)
{
AddToLog(ex.ToString());
PopError("Failed to run, see error in log box");
}
}
private void RunWorker(string url)
{
var worker = new BackgroundWorker();
worker.DoWork += (sender, args) =>
{
DatabaseHelper.DisableAllJobs();
HttpRequestsHandler.HttpGet(url);
DatabaseHelper.EnableRegularJobs();
};
worker.RunWorkerCompleted += (sender, args) =>
{
StopLoading();
abortButton.Enabled = false;
if (args.Error != null)
{
PopError("Failed to run, see error in log box");
AddToLog(args.Error.ToString());
}
else
{
PopInfo("Completed successfully");
}
};
worker.RunWorkerAsync();
}
What am I doing wrong?
Thanks
Following example run background service every 10 seconds to update GUI. You can modify it as you wish. By running your thread as async task your GUI never get hang.
public frm_testform()
{
InitializeComponent();
dispatcherTimer_Tick().DoNotAwait();
}
private async Task dispatcherTimer_Tick()
{
DispatcherTimer timer = new DispatcherTimer();
TaskCompletionSource<bool> tcs = null;
EventHandler tickHandler = (s, e) => tcs.TrySetResult(true);
timer.Interval = TimeSpan.FromSeconds(10);
timer.Tick += tickHandler;
timer.Start();
while (true)
{
tcs = new TaskCompletionSource<bool>();
await Task.Run(() =>
{
// Run your background service and UI update here
await tcs.Task;
}
}
It indeed turns out I had controls.enable = false in some part of the code (I really thought it totally meant for something else), thank you all for your help!!