Windows Service always "Starting" because of infinite loop in OnStart() method - windows-services

I've written a Windows Service that periodically executes a SSIS package that moves documents from Server A to Server B.
The problem is that in order to do so, I need to use an infinite loop, which starts when the Service starts.
Naturally, I placed this loop into the OnStart() method. Unfortunately, the service never signals that it has started, since it never reaches the end of this method...
Here is the relevant code:
protected override void OnStart(string[] args)
{
Application app = new Application();
Package pkg = app.LoadFromDtsServer(#"MSDB\PullDoc", "Server", null);
while (true)
{
DTSExecResult pkgResults = pkg.Execute();//Execute the package.
EventLog.WriteEntry(pkgResults.ToString());
Thread.Sleep(1000 * 60 * 5);//Sleep at least five minutes.
}
}
I would imagine this is a common problem, given that most Services should be running indefinitely.
Any ideas on how to get this service to return that it has started?
Thanks!

You should use a System.Threading.Timer instead of an infinite loop.

Your service should do its work on a different thread. The OnStart, OnStop etc methods are there to process commands to your service from the Windows Service Control Manager (SCM), and the SCM expects them to return promptly.
Using a System.Threading.Timer as suggested by #SLaks achieves this: the timer events will be executed on a thread from the .NET Thread Pool. Your OnStart method just Enables the Timer, while the OnStop method disables it (OnPause and OnResume can do likewise if you want).

You are not doing this correctly, you should never block a function from returning and you should use a new Thread. As it was suggested, you should use a Timer object.
Here is a code snippet to show you how:
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
CopyAToB();
}
Timer timer = new Timer();
protected override void OnStart(string[] args)
{
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 60000 * 5;
timer.Enabled = true;
}
private void CopyAToB()
{
// do somethings
}

I would recommend that you use a System.Threading.Timer like suggested but here is an example of how I would implement the functionality.
In this example I have the function fire 4 times an hour and it will quickly validate if its still running from the previous call and if so skip it otherwise it will create a new thread and fire off the function.
Imports System.Threading
Public Class myService
Private myThreadingTimer As System.Threading.Timer
Private keepRunning As Boolean = False
Private processing As Boolean = False
Protected Overrides Sub OnStart(ByVal args() As String)
Dim myTimerCallback As New TimerCallback(AddressOf OnTimedEvent)
If YourCheckHere() Then
keepRunning = True
myThreadingTimer = New System.Threading.Timer(myTimerCallback, Nothing, 1000, 1000)
Else
'What you want to do here
End If
End Sub
Protected Overrides Sub OnStop()
keepRunning = False
End Sub
Private Sub OnTimedEvent(ByVal state As Object)
If Date.Now.Minute = 14 And Date.Now.Second = 31 Or Date.Now.Minute = 29 And Date.Now.Second = 31 _
Or Date.Now.Minute = 44 And Date.Now.Second = 31 Or Date.Now.Minute = 59 And Date.Now.Second = 31 _
Then
'Make Sure Its Supposed To Still Be Running
If keepRunning Then
'Make Sure The Process Is Not Already Running
If Not processing Then
'Process is not currently running lets start it
Dim myThread As New Thread(New ThreadStart(AddressOf myProcess))
myThread.Start()
End If
End If
End If
End Sub
Public Sub myProcess()
Try
' Set the processing flag so the function does not run again until complete
processing = True
'Do whatever logic you need here
Catch ex As Exception
'Since You Can Not Use A MessageBox Do Logging Or Whatever You Need Here
Finally
processing = False
End Try
End Sub
End Class

Related

F# how to stop Async.Start

Hi I have a question about async in F#.
So I have a simple procedure that runs in background that is placed in a member of a type and it looks like:
type Sender() =
member this.Start(udpConectionPool) = async {
(* Some operation that continuously sends something over udp*)
} |> Async.Start
So this starts and begins to continuously sends frames over UDP without blocking rest of the program, but from time to time i want to restart thread (let us say i want to add new endpoint it would send it to that is udpConnectionPool parameter).
I was thinking about something like dumping task to member and then:
member this.Stop() = async {
do! (*stop async start member that contains task*)
}
And then I can restart this task with updated connection pool, but I don't know if I can do that.
My question is, Is it possible to stop such task, or if not is there a better way to do it?
The standard way of cancelling F# async workflows is using a CancellationToken. When you call Async.Start, you can provide a cancellation token. When the token gets cancelled, the async workflow will stop (after the current blocking work finishes):
open System.Threading
let cts = new CancellationTokenSource()
let work = async { (* ... *) }
Async.Start(work, cts.Token)
cts.Cancel() // Sometime later from another thread
To integrate this with the Sender, you could either store the current CancellationTokenSource and have a Stop method that cancels it (if you want to keep this inside a stateful class). Alternatively, you could return IDisposable from the Start method in a way that is similar to how the Observable interface work:
type Sender () =
member this.Start(udpConnectionPool) =
let cts = new CancellationTokenSource()
let work = async { (* ... *) }
Async.Start(work, cts.Token)
{ new System.IDisposable with
member x.Dispose() = cts.Cancel() }
This way, the caller of Start is responsible for storing the returned IDisposable and disposing of it before calling Start again.

waitForConfirmsOrDie vs PublisherCallbackChannel.Listener

I need to achieve the impact of waitForConfirmsOrDie in core java implementation in spring . In core java it is achievable request wise ( channel.confirmSelect , set Mandatory , publish and Channel.waitForConfirmsOrDie(10000) will wait for 10 sec)
I implemented template.setConfirmCallback ( hope it is same as PublisherCallbackChannel.Listener) and it works great , but ack/nack is at a common place ( confirm call back ) , for the individual sender no idea like waitForConfirmsOrDie , where he is sure within this time ack hasn't came and can take action
do send methods wait for specified period internally like waitForConfirmsOrDie in spring if ack hasn't came and if publisherConfirms is enabled.
There is currently no equivalent of waitForConfirmsOrDie in the Spring API.
Using a connection factory with publisher confirms enabled calls confirmSelect() on its channels; together with a template confirm callback, you can achieve the same functionality by keeping a count of sends yourself and adding a method to your callback to wait - something like...
#Autowired
private RabbitTemplate template;
private void runDemo() throws Exception {
MyCallback confirmCallback = new MyCallback();
this.template.setConfirmCallback(confirmCallback);
this.template.setMandatory(true);
for (int i = 0; i < 10; i++) {
template.convertAndSend(queue().getName(), "foo");
}
confirmCallback.waitForConfirmsOrDie(10, 10_000);
System.out.println("All ack'd");
}
private static class MyCallback implements ConfirmCallback {
private final BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
#Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
queue.add(ack);
}
public void waitForConfirmsOrDie(int count, long timeout) throws Exception {
int remaining = count;
while (remaining-- > 0) {
Boolean ack = queue.poll(timeout, TimeUnit.MILLISECONDS);
if (ack == null) {
throw new TimeoutException("timed out waiting for acks");
}
else if (!ack) {
System.err.println("Received a nack");
}
}
}
}
One difference, though is the channel won't be force-closed.
Also, in a multi-threaded environment, you either need a dedicated template/callback per thread, or use CorrelationData to correlate the acks to the sends (e.g. put the thread id into the correlation data and use it in the callback).
I have opened AMQP-717 for us to consider providing something like this out of the box.

How do I get the current attempt number on a background job in Hangfire?

There are some database operations I need to execute before the end of the final attempt of my Hangfire background job (I need to delete the database record related to the job)
My current job is set with the following attribute:
[AutomaticRetry(Attempts = 5, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
With that in mind, I need to determine what the current attempt number is, but am struggling to find any documentation in that regard from a Google search or Hangfire.io documentation.
Simply add PerformContext to your job method; you'll also be able to access your JobId from this object. For attempt number, this still relies on magic strings, but it's a little less flaky than the current/only answer:
public void SendEmail(PerformContext context, string emailAddress)
{
string jobId = context.BackgroundJob.Id;
int retryCount = context.GetJobParameter<int>("RetryCount");
// send an email
}
(NB! This is a solution to the OP's problem. It does not answer the question "How to get the current attempt number". If that is what you want, see the accepted answer for instance)
Use a job filter and the OnStateApplied callback:
public class CleanupAfterFailureFilter : JobFilterAttribute, IServerFilter, IApplyStateFilter
{
public void OnStateApplied(ApplyStateContext context, IWriteOnlyTransaction transaction)
{
try
{
var failedState = context.NewState as FailedState;
if (failedState != null)
{
// Job has finally failed (retry attempts exceeded)
// *** DO YOUR CLEANUP HERE ***
}
}
catch (Exception)
{
// Unhandled exceptions can cause an endless loop.
// Therefore, catch and ignore them all.
// See notes below.
}
}
public void OnStateUnapplied(ApplyStateContext context, IWriteOnlyTransaction transaction)
{
// Must be implemented, but can be empty.
}
}
Add the filter directly to the job function:
[CleanupAfterFailureFilter]
public static void MyJob()
or add it globally:
GlobalJobFilters.Filters.Add(new CleanupAfterFailureFilter ());
or like this:
var options = new BackgroundJobServerOptions
{
FilterProvider = new JobFilterCollection { new CleanupAfterFailureFilter () };
};
app.UseHangfireServer(options, storage);
Or see http://docs.hangfire.io/en/latest/extensibility/using-job-filters.html for more information about job filters.
NOTE: This is based on the accepted answer: https://stackoverflow.com/a/38387512/2279059
The difference is that OnStateApplied is used instead of OnStateElection, so the filter callback is invoked only after the maximum number of retries. A downside to this method is that the state transition to "failed" cannot be interrupted, but this is not needed in this case and in most scenarios where you just want to do some cleanup after a job has failed.
NOTE: Empty catch handlers are bad, because they can hide bugs and make them hard to debug in production. It is necessary here, so the callback doesn't get called repeatedly forever. You may want to log exceptions for debugging purposes. It is also advisable to reduce the risk of exceptions in a job filter. One possibility is, instead of doing the cleanup work in-place, to schedule a new background job which runs if the original job failed. Be careful to not apply the filter CleanupAfterFailureFilter to it, though. Don't register it globally, or add some extra logic to it...
You can use OnPerforming or OnPerformed method of IServerFilter if you want to check the attempts or if you want you can just wait on OnStateElection of IElectStateFilter. I don't know exactly what requirement you have so it's up to you. Here's the code you want :)
public class JobStateFilter : JobFilterAttribute, IElectStateFilter, IServerFilter
{
public void OnStateElection(ElectStateContext context)
{
// all failed job after retry attempts comes here
var failedState = context.CandidateState as FailedState;
if (failedState == null) return;
}
public void OnPerforming(PerformingContext filterContext)
{
// do nothing
}
public void OnPerformed(PerformedContext filterContext)
{
// you have an option to move all code here on OnPerforming if you want.
var api = JobStorage.Current.GetMonitoringApi();
var job = api.JobDetails(filterContext.BackgroundJob.Id);
foreach(var history in job.History)
{
// check reason property and you will find a string with
// Retry attempt 3 of 3: The method or operation is not implemented.
}
}
}
How to add your filter
GlobalJobFilters.Filters.Add(new JobStateFilter());
----- or
var options = new BackgroundJobServerOptions
{
FilterProvider = new JobFilterCollection { new JobStateFilter() };
};
app.UseHangfireServer(options, storage);
Sample output :

setTimeOut and local function

I'm working on Ax 4.0
I'm trying to use the Object.setTimeOut method in a job with a local function, as stated in the msdn documentation :
static void setTimeOutJob()
{
Object o = new Object();
void printText()
{
;
info( "2 seconds has elapsed since the user did anything" );
}
;
// Set a Time Out with the idle flag set to false
o.setTimeOut(identifierstr(printText), 2000, false);
}
But this simple job doesn't produce anything, so it seems I'm missing something here.
Has someone worked with this ?
The setTimeout method does not work with a local function in a job.
For a working example have a look on the form tutorial_Timer instead.
Update:
The setTimeout method is a "magic" function, but it does not turn AX into a multithreading environment.
It only works while a Windows event loop is in action. In the AX context it means that a form is running and someone else is waiting for the form to complete. The sleep function does not meet the criteria.
Also the object must be "alive", calling a garbage collected object is no good!
Example (class based):
class SetTimeoutTest extends Object //Yes, extend or it will not compile
{
str test;
}
public void new()
{
super();
test = "Hello";
}
public str test()
{
return test;
}
protected void timedOut()
{;
test = "2 seconds has elapsed since the user did anything";
info(test);
}
static void main(Args args)
{
SetTimeoutTest t = new SetTimeoutTest();
FormRun fr;
;
t.setTimeOut(methodStr(SetTimeoutTest,timedOut), 2000, false);
//sleep(4000); //Does not work
fr = ClassFactory::formRunClassOnClient(new Args(formstr(CustGroup))); //Could be any form
fr.init();
fr.run();
fr.wait(); //Otherwise the t object runs out of scope
info(t.test());
}
I just don't think it works with jobs. I've used it on forms where the method is on the element level, and have done element.setTimeout and it works fine.

jedis pubsub and timeouts: how to listen infinitely as subscriber?

I'm struggling with the concept of creating a Jedis-client which listens infinitely as a subscriber to a Redis pubsub channel and handles messages when they come in.
My problem is that after a while of inactivity the server stops responding silently. I think this is due to a timeout occurring on the Jedis-client I subscribe with.
Would this likely indeed be the case? If so, is there a way to configure this particular Jedis-client to not timeout? (While other Jedispools aren't affected with some globally set timeout)
Alternatively, is there another (best practice) way of what I'm trying to achieve?
This is my code, (modified/ stripped for display) :
executed during web-server startup:
new Thread(AkkaStarter2.getSingleton()).start();
AkkaStarter2.java
private Jedis sub;
private AkkaListener akkaListener;
public static AkkaStarter2 getSingleton(){
if(singleton==null){
singleton = new AkkaStarter2();
}
return singleton;
}
private AkkaStarter2(){
sub = new Jedis(REDISHOST, REDISPORT);
akkaListener = new AkkaListener();
}
public void run() {
//blocking
sub.psubscribe(akkaListener, AKKAPREFIX + "*");
}
class AkkaListener extends JedisPubSub {
....
public void onPMessage(String pattern, String akkaChannel,String jsonSer) {
...
}
}
Thanks.
ermmm, the below solves it all. Indeed it was a Jedis thing
private AkkaStarter2(){
//0 specifying no timeout.. Overlooked this 100 times
sub = new Jedis(REDISHOST, REDISPORT,0);
akkaListener = new AkkaListener();
}

Resources