I have a Windows service that runs the following Initialize() method immediately after being instantiated.
public async virtual void Initialize()
{
bool initSuccess = false;
int retry = 1;
while (!initSuccess && retry <= 10)
{
try
{
schedulerFactory = CreateSchedulerFactory();
scheduler = GetScheduler();
initSuccess = true;
}
catch (Exception ex)
{
logger.Error(string.Format("Server initialization failed, retry #{0} of 10 / Error message: {1}", retry, ex.Message));
retry++;
}
Task startTimer = Task.Factory.StartNew(() =>
{
Thread.Sleep(10000);
});
await startTimer;
}
}
So if the initialization fails, I would like to give the server 10 more tries to start. The code that calls the above function is:
QuartzServer server = new QuartzServer();
server.Initialize();
return server;
For some reason, this Initialize() method quits after the first iteration. That means my while loop seems the be useless although I can see in my log that the Exception is caught. Can anyone detect anything wrong with the logic of the code?
Initialize is an async void method, which normally should be avoided and only be used for event handlers. The reason is that it's impossible to wait for completion for such a method since it doesn't return a Task. The first time you reach the await startTimer statement Initialize will return control to its caller so it looks like the while loop has been exited, when in fact it hasn't.
Related
I wonder how can I make Function2 run if one the Function1 fails in Fan-out/fan-in scenario:
var tasks = new Task<long>[files.Length];
for (int i = 0; i < files.Length; i++)
{
// if one of the function fails with Exception,
// orchestrator execution does not pass Task.WhenAll(tasks) point, but I want it to.
tasks[i] = backupContext.CallActivityAsync<long>(
"Function1", files[i]);
}
await Task.WhenAll(tasks);
// how to reach this point if one of the task throws exception?
await context.CallActivityAsync("Function2", null);
In other words, I want to wait all Function1 to get completed, whether it's success or not, and then run Function2.
If I wrap await Task.WhenAll(tasks); in the try{} catch{} block it does not catch the exception if one of the task is successful and runs long enough (longer than task throwing exception), ran many experiments upon it.
UPDATE
If I wrap tasks execution in try{} catch{}
try
{
await Task.WhenAll(tasks);
}
catch (Exception ex)
{
}
and Function1 looks like this
public async Task RunSubOrchestrator([OrchestrationTrigger] IDurableOrchestrationContext context)
{
if (context.GetInput<string>() == "instanceToFail")
{
throw new Exception("TestException");
}
// this is what instanceToSucced executes
int delayInSec = 0;
await Task.Delay(delayInSec * 1000);
}
catch block hits, but once I set int delayInSec = 180 it never hits, tried it many times. If successful instance overlives failed one, exception is not thrown in the orchestrator. I run Azure Functions 3
I wonder how can I make Function2 run if one the Function1 fails
You can deal with the error handling in your activity function and if it fails you can handle the error and return the response accordingly to run another activity function in your orchestration.
Handling Error in Activity Function
public static async Task<int> FunctionListResult([ActivityTrigger] int value, ILogger log)
{
try
{
var myOutputData = await DoSomething(value);
return new
{
int delayInsec = 0;
return await Task.FromResult(delayInsec * 1000);
}
}Catch(Exception Ex)
{
// Handle the exception ...
Dosomething();
return new
{
Success = false,
ErrorMessage = Ex.Message
};
}
If an activity function fails with the respective values, you can call the other activity with that information. For better handling error you can handle the error meaningfully in activity function and return the value accordingly for your orchestration.
Handling in orchestration
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
try
{
var details = ctx.GetInput<value>();
await context.CallActivityAsync("FunctionListResult", value);
}
catch (FunctionFailedException)
{
var otherDetails = GetOtherInput(< some value >);
await context.CallActivityAsync("FunctionListResult", somevalue);
}
}
Whenever we were not handling the error, the exceptions are logged, and instance completes with a failed status.
I'm working on a bug for a Windows service. The service uses a field to track a reference to a single Task. OnStart, the task executes a single method. The method has a loop inside it and calls a database on a configurable interval to monitor the work another system is doing.
protected override void OnStart(string[] args)
{
_processorTask = Task.Run(() => StartProcessor());
}
We've occasionally had an issue where the Task dies and logs the exception just fine, but the existing plumbing wasn't telling the service to stop, so our service monitors didn't know anything was wrong.
At first, I tried to add just add a call to Stop().
private void StartProcessor()
{
var processor = new PEMonitoringProcessor(_tokenSource.Token);
try
{
// The process loop is in the function. If this method exits, good or bad, the service should stop.
processor.ProcessRun();
}
catch (Exception ex)
{
// An exception caught here is most likely fatal. Log the ex and start the service shutdown.
if (log.IsFatalEnabled) { log.Fatal("A fatal error has occurred.", ex); };
}
finally
{
Stop();
}
}
However, one of my fellow devs noticed in the OnStop method that a token is used to signal the Task to stop and then it waits. If the Task calls Stop and waits for Stop to return and OnStop is waiting for the Task to end, that does not bode well for this code.
protected override void OnStop()
{
_tokenSource.Cancel();
try
{
_processorTask.Wait();
}
// logging & clean-up...
}
I considered a separate Task that doesn't get waited on by OnStop that checks the status of the first and calls Stop if the first Task is Completed, Faulted, etc., but that seemed a touch weird. I also considered raising an Event and trying something like BeginInvoke.
Intentionally stopping the service works fine because the OnStop signals via Token that a shutdown is happening. I'm trying to cover the possibility that the Task method returns or throws unexpectedly and I want the service to stop instead of becoming a zombie.
The most straightforward way I see is something like this:
protected override void OnStart(string[] args) {
_processorTask = Task.Run(() => StartProcessor());
_processorTask.ContinueWith(x => {
// x.Exception contains exception if any, maybe log it here
Stop();
}, TaskContinuationOptions.NotOnCanceled);
}
protected override void OnStop() {
//or !_processorTask.IsCompleted && !_processorTask.IsCanceled && !_processorTask.IsFaulted
if (_processorTask.Status == TaskStatus.Running) {
// only cancel and wait if still running. Won't be the case if service is stopping from ContinueWith above
_tokenSource.Cancel();
_processorTask.Wait();
}
}
Alternative way to do the same:
protected override async void OnStart(string[] args) {
_processorTask = Task.Run(() => StartProcessor());
bool cancelled = false;
try {
await _processorTask;
}
catch (OperationCanceledException) {
// cancelled
cancelled = true;
}
catch (Exception ex) {
// log it?
}
if (!cancelled)
Stop();
}
// OnStop stays the same
I have created windows service in c# and in that service, I have created 4 threads and running them the background every after 10 sec.
Below is the code:
var ThreadSize = 4;
for (int i = 0; i < ThreadSize; i++)
{
Task.Run(async () =>
{
while (1 == 1)
{
try
{
//Logic
await Task.Delay(10000, cancelSource.Token);
}
catch (Exception ex)
{
//Log the exception
}
}
});
}
The for loop will be executed only once and will create 4 threads. I am using Task.Delay to wait the thread for 10 sec and then again executing my logic. It will go and execute my logic every 10 sec.
The code is working fine, but after some time, my all threads getting terminated (Not working). I mean, the code in the logic is not working after couples of hours.
There is no exception at all.
Can any one suggested what went wrong.
Thanks you in advance.
Edited Code:
CancellationTokenSource cancelSource;
protected override void OnStart(string[] args)
{
cancelSource = new CancellationTokenSource();
Process.StartProcess(cancelSource);
}
protected override void OnStop()
{
cancelSource.Cancel();
}
public static void StartProcess(CancellationTokenSource cancelSource)
{
var ThreadSize = 4;
for (int i = 0; i < ThreadSize; i++)
{
Task.Run(async () =>
{
while (1 == 1)
{
try
{
//Logic
await Task.Delay(10000, cancelSource.Token);
}
catch (Exception ex)
{
//Log the exception
}
}
});
}
}
If any exception occurs within the Task.Run, it will be saved and thrown when the task is awaited. You're not awaiting the task, so any exception that has occurred won't be visible.
You should await the Task.Run by either using the await keyword or call .Wait() on it.
As you're spawning multiple tasks, you could add all of them to a list and then call await Task.WhenAny(tasks) which will return when any of the tasks finishes, so you can act accordingly.
Read this article for more information
Your main problem is in
catch (Exception ex)
{
throw;
}
This effectively means that you don't catch any errors. You might as well remove the try/catch for the same effect, or lack of effect.
The main structure of your Service looks OK, this won't stop by itself. The choice of Task vs Thread is not too important.
Your error happens inside //Logic and is not handled.
You will need some form of logging to find out.
I`m working on implementing a get method for cache. This method will return to caller if a maximum wait time has passed(in my case 100ms for tests).
My issue is that the exception NEVER reaches the catch, after the timer triggered the event.
Please help me understand why? (I read that events are executed on the same thread, so that should`t be the issue)
public static T Get<T>(string key, int? maxMilisecondsForResponse = null)
{
var result = default(T);
try
{
// Return default if time expired
if (maxMilisecondsForResponse.HasValue)
{
var timer = new System.Timers.Timer(maxMilisecondsForResponse.Value);
timer.Elapsed += OnTimerElapsed;
timer.AutoReset = false;
timer.Enabled = true; // start the timer
}
var externalCache = new CacheServiceClient(BindingName);
Thread.Sleep(3000); // just for testing
}
catch (Exception ex)
{
// why is the exception not caught here?
}
return result;
}
private static void OnTimerElapsed(object source, System.Timers.ElapsedEventArgs e)
{
throw new Exception("Timer elapsed");
}
The timer fires on it's own thread. You can read more about it in this answer.
The answer to your question is to use async methods that can be cancelled. Then you can use a cancellation token source and do it the proper way instead of homebrewing a solution with timers.
You can find a good overview here.
For example:
cts = new CancellationTokenSource();
cts.CancelAfter(2500);
await Task.Delay(10000, cts.Token);
This would cancel the waiting task after 2500 (of 10000) because it took too long. Obviously you need to insert your own logic in a task instead of just waiting.
From MSDN
The Timer component catches and suppresses all exceptions thrown by
event handlers for the Elapsed event. This behavior is subject to
change in future releases of the .NET Framework.
And continues
Note, however, that this is not true of event handlers that execute
asynchronously and include the await operator (in C#) or the Await
operator (in Visual Basic). Exceptions thrown in these event handlers
are propagated back to the calling thread.
Please take a look Exception Handling (Task Parallel Library)
An applied example below:
public class Program
{
static void Main()
{
Console.WriteLine("Begin");
Get<string>("key", 1000);
Console.WriteLine("End");
}
public static T Get<T>(string key, int? maxMilisecondsForResponse = null)
{
var result = default(T);
try
{
var task = Task.Run(async () =>
{
await Task.Delay(maxMilisecondsForResponse.Value);
throw new Exception("Timer elapsed");
});
task.Wait();
}
catch (Exception ex)
{
// why the exception is not catched here?
Console.WriteLine(ex);
}
return result;
}
}
The timer is being executed in the own thread but you can't catch the exception at the caller level. So, it is not a good approach to use timer in this case and you can change it by creating the Task operation.
var result = default(T);
CacheServiceClient externalCache;
if (!Task.Run(() =>
{
externalCache = new CacheServiceClient(BindingName);
return externalCache;
}).Wait(100))//Wait for the 100 ms to complete operation.
{
throw new Exception("Task is not completed !");
}
// Do something
return result;
I have some kind of data processing, that is depnded on the success of problematic method that returns a result that used in my processing.
The external method is problematic since it works slowly, it may crash and throw exceptions of any type, and I don't have its source code.
I want to use thread in the beginning of my processing to save some time, since my processing is long enough even without that problematic method. but there exists a point that I must have a valid result from the problematic method that I cannot continue if it fails.
I want the use the exceptions of the problematic method in the main thread, so they get the same exception handling as any other exceptions that may be thrown by my processing.
Here is my code - it seems ok and it works, but it just looks too cumbersome to me, so this my question: Is there a better approach to manage correctly the call to the problematic method by thread, and its potential exceptions?
My environment is .NET 3.5, so please I would like to get answers focusing that version, but I would like also to learn if there are new approaches for newer .NET versions.
Thank you very much!
public void DoProcess()
{
object locker = new object();
bool problematicCodeFinished = false;
Exception methodException = null;
Result result;
Func<Result> getProblematicResult = new Func<Result>(() => problematicMethod()); //create delegate
//run problematic method it in thread
getProblematicResult.BeginInvoke((ar) => //callback
{
lock(locker)
{
try
{
result = getProblematicResult.EndInvoke();
}
catch (Exception ex)
{
methodException = ex;
}
finally
{
problematicCodeFinished = true;
Monitor.Pulse(locker);
}
}
}, null);
//do more processing in main thread
// ...
// ...
// ...
try
{
//here we must know what was the result of the problematic method
lock (locker)
{
if (!problematicCodeFinished) //wait for problematic method to finish
{
Monitor.Wait(locker);
}
}
//throw problematic method exception in main thread
if (methodException != null)
{
throw methodException;
}
//if we are here we can assume that we have a valid result, continue processing
// ...
// ...
// ...
}
catch (Exception ex) //for the problematic method exception, or any other exception
{
//normal exception handling for my processing
}
}
You're making life hard for yourself. Try using tasks from the TPL instead.
Your code would look like this:
public void DoProcess()
{
var task = Task.Factory.StartNew(() => problematicMethod());
//do more processing in main thread
// ...
// ...
// ...
var result = task.Result;
}