Long running task in workflow foundation 4 - c#

I have an application in which there are long running process, to handle that i have used Windows Workflow4
Process depends on number of users
If number of users are less i.e. 30-100 then it is working fine and if greater than 500 then there is problem
My problem is even if the Workflow process is completed View is showing processing but in backend it is completed
Workflow code
WorkflowApplication application;
application = new WorkflowApplication(new Payroll_Workflow.PayrollProcess(), inputparam);
application.SynchronizationContext = new SynchronousSynchronizationContext();
//we assign a delegate for the Completed event of the application
application.Completed = delegate(WorkflowApplicationCompletedEventArgs completedEvent)
{
if (completedEvent.TerminationException != null)
{
communicationMessage.message = completedEvent.TerminationException.Message.Replace("_", " ");
//ErrorMessages error = (ErrorMessages)Enum.Parse(typeof(ErrorMessages), completedEvent.TerminationException.Message.Replace(" ", "_"));
}
else
{
communicationMessage.message = "Process Completed";
}
};
//we start the application
application.Run();

Are your workflows all reaching "communicationMessage.message = "Process Completed";" ?
If they are then perhaps this communication process is being overwhelmed?

Related

MVC 5 - IIS Stops Tasks Thread

I have a thread that shoots events to run programs at certain times.
I do want the website to have full control over the process so that is why I built it into the site as a long term thread that loops.
The issue is I scheduled a task to happen at a particular time and it happens almost randomly (maybe when I load the page). It seems as if the web app sleeps all threads until its used or something.
Here is the code:
public void run()
{
Task.Factory.StartNew(() =>
{
while (true)
{
var lastDate = InternalEventLogger.GetLastDateTime();
if (DateTime.Now >= lastDate.AddDays(1))
{
System.Diagnostics.Debug.WriteLine(DateTime.Now);
System.Diagnostics.Debug.WriteLine(lastDate.AddDays(1));
InternalEventLogger.RefreshLog();
}
bool needUpdate = false;
System.Diagnostics.Debug.WriteLine("this");
List<Event> tempList = new List<Event>(this.evtList.getList());
foreach (Event evt in this.evtList.getList())
{
if (!evt.status.Equals("success"))
continue;
if (evt.nextRun <= DateTime.Now)
{
var tempEvt = evt;
System.Diagnostics.Debug.WriteLine("time to run: "+evt.name);
tempList.Remove(evt);
tempEvt.nextRun = evt.nextRun.AddMinutes(evt.interval);
tempEvt.lastRan = DateTime.Now;
tempList.Add(tempEvt);
needUpdate = true;
if (tempEvt.runLocation != null)
Task.Factory.StartNew(() =>
{
Process p = new Process();
p.StartInfo.FileName = tempEvt.runLocation;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.Start();
string output = p.StandardOutput.ReadToEnd();
string err = p.StandardError.ReadToEnd();
InternalEventLogger.WriteLog(output);
InternalEventLogger.WriteLog("// ------------- ERROR -------------- \n" + err);
p.WaitForExit();
});
}
}
if (needUpdate)
{
this.evtList.setList(tempList);
this.evtList.serialize(ConfigurationManager.AppSettings["xmlEventLocation"]);
}
Thread.Sleep(10000);
}
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
Ran from:
private static void RegisterServices(IKernel kernel)
{
evtManager = new EventManager(ConfigurationManager.AppSettings["xmlEventLocation"]);
evtManager.run();
// Initalize Event Logger
new InternalEventLogger();
}
Here is a pic that shows the problem in timing:
IIS Settings below
Only at visit does it start the tasks.
Open that settings dialog in your IIS Manager.
Make sure you have:
Start Mode = AlwaysRunning
Idle Time-out (minutes) = 0
for the application pool you are using - test the settings so that you are sure you are editing the correct pool.
If you have this, your application should be running all the time, but there is one more thing - Recycling - at the bottom of that setting dialog, set up your Recycling as you need it. It might be the case that you are OK with the defaults, but if you are not aware of Recycling, it might surprise you, so make sure you understand it and configure the settings as you need it.
Yes, you are right, the IIS hosting do not stores the threads, as all the Web Application has to do is handle the request and provide the response. If you want to run the task on schedule, you really shouldn't use the web application, as it cancels all the background threads after the response is sent.
I suggest you to change your architecture, and create a Windows service (like daemon) which will start automatically after system boot, and which can much more easily control the event firing.
If for somewhat reason you want a web interface for such method, you can use a WCF binding between your web application and windows service (over TCP/IP or named pipes or whatever), but your approach wouldn't work for Web Application.
I want also to point out that this code:
while (true)
is a bad idea - you should use a CancellationToken for your task in this case.

MVC 5 - Ninject - Tasks Thread Running Oddly

I have a thread that shoots events to run programs at certain times.
I do want the website to have full control over the process so that is why I built it into the site as a long term thread that loops.
The issue is I scheduled a task to happen at a particular time and it happens almost randomly (maybe when I load the page). It seems as if the web app sleeps all threads until its used or something.
Here is the code:
public void run()
{
Task.Factory.StartNew(() =>
{
while (true)
{
var lastDate = InternalEventLogger.GetLastDateTime();
if (DateTime.Now >= lastDate.AddDays(1))
{
System.Diagnostics.Debug.WriteLine(DateTime.Now);
System.Diagnostics.Debug.WriteLine(lastDate.AddDays(1));
InternalEventLogger.RefreshLog();
}
bool needUpdate = false;
System.Diagnostics.Debug.WriteLine("this");
List<Event> tempList = new List<Event>(this.evtList.getList());
foreach (Event evt in this.evtList.getList())
{
if (!evt.status.Equals("success"))
continue;
if (evt.nextRun <= DateTime.Now)
{
var tempEvt = evt;
System.Diagnostics.Debug.WriteLine("time to run: "+evt.name);
tempList.Remove(evt);
tempEvt.nextRun = evt.nextRun.AddMinutes(evt.interval);
tempEvt.lastRan = DateTime.Now;
tempList.Add(tempEvt);
needUpdate = true;
if (tempEvt.runLocation != null)
Task.Factory.StartNew(() =>
{
Process p = new Process();
p.StartInfo.FileName = tempEvt.runLocation;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.Start();
string output = p.StandardOutput.ReadToEnd();
string err = p.StandardError.ReadToEnd();
InternalEventLogger.WriteLog(output);
InternalEventLogger.WriteLog("// ------------- ERROR -------------- \n" + err);
p.WaitForExit();
});
}
}
if (needUpdate)
{
this.evtList.setList(tempList);
this.evtList.serialize(ConfigurationManager.AppSettings["xmlEventLocation"]);
}
Thread.Sleep(10000);
}
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
Ran from:
private static void RegisterServices(IKernel kernel)
{
evtManager = new EventManager(ConfigurationManager.AppSettings["xmlEventLocation"]);
evtManager.run();
// Initalize Event Logger
new InternalEventLogger();
}
Here is a pic that shows the problem in timing:
UPDATE
Tried the settings below and still not working properly!
Only at visit does it start the tasks.
May be problem in your IIS web server settings. IIS Application Pool have parameter (in advanced settings): Idle Time-out (minutes). By default this settings is 20 minutes. So when there are no queries to web site during 20 minutes web server stops Application Pool process.
Idle Time-out parameter explanation.
Link to Microsoft Technet
Recycling timer on IIS Settings needed to be changed.

Windows Service stuck on "starting" status as local system account

I developed a http server via console application in C# and decided to turn it into a Windows service to be able to initialize it without the need to login the machine.
I followed all the steps in How to create Windows Service and chose the account as "Local System", but when I install in my server machine and push the start button it takes a while and gives the following error:
Erro 1053: The service did not respond to the start or control request in timely fashion.
After that, the service status stays stuck in "starting" and the application don't work and I can't even stop the service anymore.
Trying to work around this problem, I changed it to "Network Service", so it started normally, but the application was not listening in the port I set when I checked in the prompt with the command "netstat -an". But the application listens normally if i run it as a console application.
So I am looking for an answer to one of these two questions:
What should I do to make the service starts properly with a Local System account?
If I decide to use Network service account, what should I care about to guarantee that my service works properly as a server?
When I converted my console application to windows service I simply put my code directly in the OnStart method. However, I realized the OnStart method should start the service, but needs to end some time to the service indeed start. So I created a thread that runs my service and let the OnStart method finish. I tested and the service worked just fine. Here is how it was the code:
protected override void OnStart(string[] args)
{
Listener(); // this method never returns
}
Here is how it worked:
protected override void OnStart(string[] args)
{
Thread t = new Thread(new ThreadStart(Listener));
t.Start();
}
But I still don't understand why the service ran (passed the "starting" status, but didn't work) when I used network service account. If anyone knows, I'll be glad to know the reason.
If you have a service that is not responding or showing pending in Windows services that you are unable to stop, use the following directions to force the service to stop.
Start -> Run or Start -> type services.msc and press Enter
Look for the service and check the Properties and identify its service name
Once found, open a command prompt. Type sc queryex [servicename]
Identify the PID (process ID)
In the same command prompt type taskkill /pid [pid number] /f
Find PID of Service
sc queryex <SERVICE_NAME>
Give result's below
SERVICE_NAME: Foo.Services.Bar TYPE : 10 WIN32_OWN_PROCESS STATE : 2 0 START_PENDING (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN) WIN32_EXIT_CODE : 0 (0x0) SERVICE_EXIT_CODE : 0 (0x0) CHECKPOINT : 0x0 WAIT_HINT : 0x0 PID : 3976 FLAGS :
Now Kill the Service:
taskkill /f /pid 3976
SUCESS: The process with PID 3976 has been terminated.
Check the Windows Application event log, it could contain some entries from your service's auto generated event source (which should have the same name of the service).
For me it was a while loop that looked at an external queue. The while-loop continued running until the queue was empty. Solved it by calling a timer event directly only when Environment.UserInteractive. Therefore the service could be debugged easily but when running as a service it would wait for the timers ElapsedEventHandler event.
Service:
partial class IntegrationService : ServiceBase
{
private static Logger logger = LogManager.GetCurrentClassLogger();
private System.Timers.Timer timer;
public IntegrationService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
// Add code here to start your service.
logger.Info($"Starting IntegrationService");
var updateIntervalString = ConfigurationManager.AppSettings["UpdateInterval"];
var updateInterval = 60000;
Int32.TryParse(updateIntervalString, out updateInterval);
var projectHost = ConfigurationManager.AppSettings["ProjectIntegrationServiceHost"];
var projectIntegrationApiService = new ProjectIntegrationApiService(new Uri(projectHost));
var projectDbContext = new ProjectDbContext();
var projectIntegrationService = new ProjectIntegrationService(projectIntegrationApiService, projectDbContext);
timer = new System.Timers.Timer();
timer.AutoReset = true;
var integrationProcessor = new IntegrationProcessor(updateInterval, projectIntegrationService, timer);
timer.Start();
}
catch (Exception e)
{
logger.Fatal(e);
}
}
protected override void OnStop()
{
try
{
// Add code here to perform any tear-down necessary to stop your service.
timer.Enabled = false;
timer.Dispose();
timer = null;
}
catch (Exception e)
{
logger.Fatal(e);
}
}
}
Processor:
public class IntegrationProcessor
{
private static Logger _logger = LogManager.GetCurrentClassLogger();
private static volatile bool _workerIsRunning;
private int _updateInterval;
private ProjectIntegrationService _projectIntegrationService;
public IntegrationProcessor(int updateInterval, ProjectIntegrationService projectIntegrationService, Timer timer)
{
_updateInterval = updateInterval;
_projectIntegrationService = projectIntegrationService;
timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
timer.Interval = _updateInterval;
//Don't wait for first elapsed time - Should not be used when running as a service due to that Starting will hang up until the queue is empty
if (Environment.UserInteractive)
{
OnTimedEvent(null, null);
}
_workerIsRunning = false;
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
try
{
if (_workerIsRunning == false)
{
_workerIsRunning = true;
ProjectInformationToGet infoToGet = null;
_logger.Info($"Started looking for information to get");
//Run until queue is empty
while ((infoToGet = _projectIntegrationService.GetInformationToGet()) != null)
{
//Set debugger on logger below to control how many cycles the service should run while debugging.
var watch = System.Diagnostics.Stopwatch.StartNew();
_logger.Info($"Started Stopwatch");
_logger.Info($"Found new information, updating values");
_projectIntegrationService.AddOrUpdateNewInformation(infoToGet);
_logger.Info($"Completed updating values");
watch.Stop();
_logger.Info($"Stopwatch stopped. Elapsed seconds: {watch.ElapsedMilliseconds / 1000}. " +
$"Name queue items: {infoToGet.NameQueueItems.Count} " +
$"Case queue items: {infoToGet.CaseQueueItems.Count} " +
$"Fee calculation queue items: {infoToGet.FeeCalculationQueueItems.Count} " +
$"Updated foreign keys: {infoToGet.ShouldUpdateKeys}");
}
_logger.Info($"Nothing more to get from integration service right now");
_workerIsRunning = false;
}
else
{
_logger.Info($"Worker is already running! Will check back again after {_updateInterval / 1000} seconds");
}
}
catch (DbEntityValidationException exception)
{
var newException = new FormattedDbEntityValidationException(exception);
HandelException(newException);
throw newException;
}
catch (Exception exception)
{
HandelException(exception);
//If an exception occurs when running as a service, the service will restart and run again
if (Environment.UserInteractive)
{
throw;
}
}
}
private void HandelException(Exception exception)
{
_logger.Fatal(exception);
_workerIsRunning = false;
}
}
You can try to increase the windows service timeout with a key in the registry
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
"ServicesPipeTimeout"=dword:300000 (300 seconds or 5 minutes)
If it doesn't exists it has to be created.

C# - Accessing the STDIN and STDOUT handles of a process without redirecting them

I'm trying to access the input and output streams of a process my application starts. My code is:
this.App = new Process();
this.App.StartInfo.FileName = this.AppPath;
this.App.StartInfo.Arguments = this.AppArgs;
this.App.StartInfo.RedirectStandardOutput = true;
this.App.StartInfo.UseShellExecute = false;
this.App.Start();
ThreadStart ts = new ThreadStart(() =>
{
while (true)
{
if (this.App.StandardOutput != null && !this.App.StandardOutput.EndOfStream)
{
Console.Write((char)this.App.StandardOutput.Read());
}
}
}
this.listener = new Thread(ts);
this.listener.IsBackground = true;
this.listener.Start();
this.App.WaitForExit();
The code does work perfectly. It prints any output of the spawned process into console. The problem is, that the spawned process is a Source Dedicated Server, which doesn't like when it's STDIN/STDERR/STDOUT handles are redirected - throws up an error MessageBox and dies once it's closed. I have spent hours trying to mess with kernel32.dll, but failed.
I'm looking for a way to access the handles/output of the spawned process without redirecting them, as I'm obviously not allowed to do that.
Anyone?
Please.

how to make sure my process that i am starting will close of my application crash

in my application i m open Wireshark process and start capturing packts, in the UI i have Start button who start the capturing and Stop button who stop capturing and i am doing this by killing my wireshark process.
my question is if i am close my application in the middle of the capturing but nor with my Stop button my Wireshark process continue to run, how can i handle this situation and make sure that my process will close if my application crash or someone close it in the middle of capturing
public void startCapturing()
{
ThreadStart tStarter = delegate { openAdapterForStatistics(_device); };
Thread thread = new Thread(tStarter);
thread.IsBackground = true;
thread.Start();
ProcessStartInfo tsharkStartInfo = new ProcessStartInfo();
tsharkStartInfo.FileName = _tshark;
tsharkStartInfo.RedirectStandardOutput = true;
tsharkStartInfo.RedirectStandardError = true;
tsharkStartInfo.RedirectStandardInput = true;
tsharkStartInfo.UseShellExecute = false;
tsharkStartInfo.CreateNoWindow = true;
tsharkStartInfo.Arguments = string.Format(" -i " + _interfaceNumber + " -s " + _packetLimitSize + " -w " + _pcapPath);
_tsharkProcess.StartInfo = tsharkStartInfo;
_tsharkProcess.ErrorDataReceived += _cmdProcess_ErrorDataReceived;
_tsharkProcess.OutputDataReceived += tshark_OutputDataReceived;
_tsharkProcess.EnableRaisingEvents = true;
_tsharkProcess.Start();
_tsharkProcess.BeginOutputReadLine();
_tsharkProcess.BeginErrorReadLine();
FileInfo fileInfo = new FileInfo(_pcapPath);
string directoryName = fileInfo.DirectoryName;
DirectoryInfo directoryInfo = new DirectoryInfo(directoryName);
FileInfo[] dirs = directoryInfo.GetFiles();
_file = dirs.FirstOrDefault(f => f.Name.Equals(fileInfo.Name));
_tsharkProcess.WaitForExit();
}
Assuming you're handling exceptions using try-catch, you can make sure the Wireshark process is closed in the finally block at the end of your topmost try-catch statement. From the MSDN documentation:
"The finally block is useful for cleaning up any resources allocated in the try block. Control is always passed to the finally block regardless of how the try block exits."
For example:
try
{
// Your application's code.
}
catch( Exception )
{
// Handle, log, whatever.
}
finally
{
// Make sure Wireshark process is killed.
}
The code in the finally block will always get executed whether or not there was an exception.
You can't be 100% sure. If your application crashes in a 'civilized' manner, you can close the Wireshark process (much like #jebar8 suggested). Unfortunately, your application could crash in a way that doesn't run your finally code (if it's out of memory or your main thread is out of stack space, for example).
If you want to take that into account as well, you need a third process. Write up a small program that will launch your application and monitor it. If your application process disappears, your monitoring process can then kill Wirehsark is it's alive. Since the monitoring program is a short and simple one, the chance of it crashing unexpectedly are very slim.

Categories

Resources