Increasing a timer everytime an evaluation is false - c#

I'm measuring the amount of time certain actions in Internet Explorer take. One of the actions I'm measuring is launching another application via a link in IE. To measure how long this application takes to launch I start a timer after the link has been clicked in IE and I had planned on stopping it once the application had fully loaded. The problem there was that my application would go to execute the next line since the evaluation would always be false as there wasn't enough time between lines for the external app to load.
try
{
Process[] externApp = Process.GetProcessesByName("External");
System.Timers.Timer runningWindow = new System.Timers.Timer(1000);
runningWindow.Start();
while (runningWindow.Enabled)
{
if (externApp[0].Responding)
{
timer.Stop();
output[2] = timer.Elapsed.Seconds.ToString();
runningWindow.Stop();
}
runningWindow.Interval += 100;
}
externApp[0].Kill();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
Above is how I'm currently trying to get my application to hang while I wait for the other application to respond.
Since I wasn't sure how to wait for another application to load I decided to use a timer to postpone the execution of the next line after I check if the other application is running. If the application wasn't running I would increase the timer by a tenth of a second then check again. However the problem I was running into here is that I don't think I'm increasing the timer as my time measurement is always 0 for this step.
So how do I increase my timer if my external application isn't responding?

Albeit unreliable for the reasons explained above in comments you can still use the Process.WaitForInputIdle to get an approximate evaluation of the startup time required by your app
// Launch the external app...
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = #"D:\temp\MyExternalApp.exe";
psi.WorkingDirectory = #"D:\temp";
// Init measure
Stopwatch sw = StopWatch.StartNew();
Process.Start(psi);
Process[] externApp = null;
int cnt = 0;
bool ready = false;
while (externApp == null || externApp.Length == 0 || cnt == 600)
{
// Loop until the process appears in the process list.
// This is taxing for the performances. Heisenberg here
externApp = Process.GetProcessesByName("MyExternalApp");
Thread.Sleep(100);
cnt++;
}
if(cnt >= 600)
MessageBox.Show("Something has gone terribly wrong launching the external app");
else
ready = externApp[0].WaitForInputIdle(30000);
sw.Stop();
if(!ready)
MessageBox.Show("Not ready after:" + sw.ElapsedMilliseconds + " ms");
else
MessageBox.Show("Ready after:" + sw.ElapsedMilliseconds + " ms");
Another approch could be used (still with WaitForInputIdle) if you cannot start a Stopwatch the exact instant in which your external process has been started (like it seems with your comment about starting the ExternalApp through a browseer) In this case we could try to get the start time using the same named property in the Process class
Process[] externApp = null;
int cnt = 0;
bool ready = false;
while (externApp == null || externApp.Length == 0 || cnt == 600)
{
// Again we are waiting to see the process in the list of processes
externApp = Process.GetProcessesByName("MyExternalApp");
Thread.Sleep(100);
cnt++;
}
if(cnt >= 600)
MessageBox.Show("Something has gone terribly wrong launching the external app");
else
{
ready = externApp[0].WaitForInputIdle(30000);
DateTime readyAt = DateTime.Now;
TimeSpan ts = readyAt - externApp[0].StartTime;
MessageBox.Show("Ready after:" + ts.TotalMilliseconds + " ms");
}

You can simply get the Current time before starting IE:
DateTime start = DateTime.Now;
And in the end subtract it from the finish time like:
double SecondsElapsed = (DateTime.Now-start).TotalSeconds;

Related

using Networkinformation.Ping in for loop somehow freeze my computer and causing blue screen of death c# [duplicate]

I'm running into the bug where it BSODon ending debugging in the middle of a ping.
I have a few ways to disable it in my (wpf) application (where I ping continuously), but sometimes I forget to do so and BSOD.
I'd like to get around that say by changing a global AllowRealPinging variable and sleeping for 2 seconds in a callback before exiting the debugger so I don't BSOD.
This is a known bug in Windows 7, you'll get a BSOD with bug-check code 0x76, PROCESS_HAS_LOCKED_PAGES in tcpip.sys when you terminate the process. The most relevant feedback article is here. Also covered in this SO question. No great answers there, the only known workaround is to fallback to a .NET version earlier than 4.0, it uses another winapi function that doesn't trigger the driver bug.
Avoiding pinging while you debug is certainly the best way to avoid this problem. Your desired approach is not going to work, your program is entirely frozen when it hits a breakpoint, kaboom when you stop debugging.
The simplest way is to just not starting pinging in the first place in the specific case of having a debugger attached. Use the System.Diagnostic.Debugger.IsAttached property to detect this in your code.
This is a good way around:
private void GetPing(){
Dictionary<string, string> tempDictionary = this.tempDictionary; //Some adresses you want to test
StringBuilder proxy = new StringBuilder();
string roundTripTest = "";
string location;
int count = 0; //Count is mainly there in case you don't get anything
Process process = new Process{
StartInfo = new ProcessStartInfo{
FileName = "ping.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true,
}
};
for (int i = 0; i < tempDictionary.Count; i++){
proxy.Append(tempDictionary.Keys.ElementAt(i));
process.StartInfo.Arguments = proxy.ToString();
do{
try{
roundTripTest = RoundTripCheck(process);
}
catch (Exception ex){
count++;
}
if (roundTripTest == null){
count++;
}
if (count == 10 || roundTripTest.Trim().Equals("")){
roundTripTest = "Server Unavailable";
}
} while (roundTripTest == null || roundTripTest.Equals(" ") || roundTripTest.Equals(""));
}
process.Dispose();
}
RoundTripCheck method, where the magic happens:
private string RoundTripCheck(Process p){
StringBuilder result = new StringBuilder();
string returned = "";
p.Start();
while (!p.StandardOutput.EndOfStream){
result.Append(p.StandardOutput.ReadLine());
if (result.ToString().Contains("Average")){
returned = result.ToString().Substring(result.ToString().IndexOf("Average ="))
.Replace("Average =", "").Trim().Replace("ms", "").ToString();
break;
}
result.Clear();
}
return returned;
}
I had the same problem, this solves it!

What is breaking my Process.StartInfo.OutputDataReceived callbacks prematurely?

The following problem occurs on .NET Framework v3.5. Don't know if it applies to v4*.
To capture stdout for some processes I've successfully used p.StartInfo.UseShellExecute = false; and p.StartInfo.RedirectStandardOutput = true; and an event handler hooked to p.StartInfo.OutputDataReceived+=...;. Then I call p.Start(); then p.BeginOutputReadLine(); and then p.WaitForExit();
All is well so far. I get all stdout on the event handler, line by line, as expected.
I had to introduce a timeout instead of WaitForExit() because some processes unpredictably trigger requests for input at stdin (e.g. are you sure? [y/n]) leading to a deadlock where I wait forever and so do they.
The first thing I tried is changing to while (!p.HasExited && DateTime.Now < timeoutmom) p.WaitForExit(200); where timeoutmoment is 2 minutes after proc.Start(). This is when I ran into problems. Very consistently, the code works for calls that produce up to a few hundred lines of stdout but it breaks for one call that produces about 7500 lines. What happens is the proc.WaitForExit(200); thread exits the while when my OutputDataReceived event handler was called for only ~ 7300 lines (this number is again very consistent it varies by only +/- 1 between tests) and the handler is not called anymore for the rest of the stdout lines so I lose them.
Strangely, the problem doesn't appear if I avoid WaitForExit(200) and instead use while (!p.HasExited && DateTime.Now < timeoutmom) System.Threading.Thread.Sleep(1000); (not shown in the code below). When I posted the question I was pretty sure the problem was avoided using Sleep(1000) but I was wrong. It worked a few dozen times like that and then it didn't, it started behaving just like when I checked WaitForExit(200).
I now speculate that the reasons for this problem are (1) I take too long to process each OutputDataReceived callback. I noticed the problem was aggravated when I added a conditional breakpoint in the event handler which lengthened the method execution by a lot. I can now reproduce the problem by simply adding 3x Debug.WriteLines without the conditional breakpoint; PLUS (2) my context is somehow corrupted by me accessing HasExited / WaitForExit(200) before the system had a chance to perform all the callbacks on my event handler. I now do a blind System.Threading.Thread.Sleep(30000) just after p.Start() and before accessing any p.* method and I get all the callbacks. When I used WaitForExit() it seemed I can take however much time I want to process every callback and I would still get them all.
Can someone make more sense of this?
Code:
private int _execOsProc(
ProcessStartInfo Psi
, string SecInsensArgs
, TextWriter ExtraStdOutAndErrTgt
, bool OutputToExtraStdOutOnly
)
{
var pr = new Process();
pr.StartInfo = Psi;
pr.StartInfo.UseShellExecute = false;
pr.StartInfo.RedirectStandardOutput = pr.StartInfo.RedirectStandardError = true;
pr.StartInfo.CreateNoWindow = true;
var ol = new DataReceivedEventHandler(this._stdOutDataReceived);
var el = new DataReceivedEventHandler(this._stdErrDataReceived);
pr.OutputDataReceived += ol;
pr.ErrorDataReceived += el;
try
{
__logger.Debug("Executing: \"" + pr.StartInfo.FileName + "\" " + SecInsensArgs);
if (ExtraStdOutAndErrTgt == null)
{
this.__outputToExtraStdOutOnly = false;
}
else
{
this.__extraStdOutAndErrTgt = ExtraStdOutAndErrTgt;
this.__outputToExtraStdOutOnly = OutputToExtraStdOutOnly;
}
pr.Start();
pr.BeginOutputReadLine();
pr.BeginErrorReadLine();
var startmom = DateTime.Now;
var timeoutmom = startmom.AddMinutes(2);
while (!pr.HasExited && DateTime.Now < timeoutmom) pr.WaitForExit(200);
pr.CancelOutputRead();
pr.CancelErrorRead();
if (pr.HasExited)
{
__logger.Debug("Execution finished with exit status code: " + pr.ExitCode);
return pr.ExitCode;
}
else
{
__logger.Debug("Timeout while waiting for execution to finish");
pr.Kill();
return -100;
}
}
finally
{
pr.OutputDataReceived -= ol;
pr.ErrorDataReceived -= el;
if (this.__extraStdOutAndErrTgt != null)
{
this.__extraStdOutAndErrTgt = null;
this.__outputToExtraStdOutOnly = false;
}
}
}
private void _stdOutDataReceived(
object sender
, DataReceivedEventArgs e
)
{
string rdata = string.IsNullOrEmpty(e.Data) ? "" : e.Data.Trim();
if (!this.__outputToExtraStdOutOnly) __logger.Debug("SO: " + rdata);
if (this.__extraStdOutAndErrTgt != null)
{
lock (this.__extraStdOutAndErrTgt)
{
try
{
this.__extraStdOutAndErrTgt.WriteLine(rdata);
this.__extraStdOutAndErrTgt.Flush();
}
catch (Exception exc)
{
__logger.Warn(
"WARNING: Error detected but ignored during extra stream write"
+ " on SODR. Details: " + exc.Message
, exc
);
}
}
}
}
private void _stdErrDataReceived(
object sender
, DataReceivedEventArgs e
)
{
string rdata = string.IsNullOrEmpty(e.Data) ? "" : e.Data.Trim();
if (!__outputToExtraStdOutOnly) __logger.Debug("SE: " + rdata);
if (this.__extraStdOutAndErrTgt != null)
{
lock (this.__extraStdOutAndErrTgt)
{
try
{
this.__extraStdOutAndErrTgt.WriteLine(rdata);
this.__extraStdOutAndErrTgt.Flush();
}
catch (Exception exc)
{
__logger.Warn(
"WARNING: Error detected but ignored during extra stream write"
+ " on SEDR. Details: " + exc.Message
, exc
);
}
}
}
}
I'm not sure if it will solve the problem, but it is too long to post it in the comment.
MSDN says about Process.HasExited:
When standard output has been redirected to asynchronous event
handlers, it is possible that output processing will not have
completed when this property returns true. To ensure that asynchronous
event handling has been completed, call the WaitForExit() overload
that takes no parameter before checking HasExited.
and about WaitForExit():
This overload ensures that all processing has been completed,
including the handling of asynchronous events for redirected standard
output. You should use this overload after a call to the
WaitForExit(Int32) overload when standard output has been redirected
to asynchronous event handlers.
It indicates, that call to WaitForExit() with no parameters should solve the problem. Something like:
var startmom = DateTime.Now;
var timeoutmom = startmom.AddMinutes(2);
while (!pr.HasExited && DateTime.Now < timeoutmom)
pr.WaitForExit(200);
if (pr.HasExited)
{
WaitForExit();//Ensure that redirected output buffers are flushed
pr.CancelOutputRead();
pr.CancelErrorRead();
__logger.Debug("Execution finished with exit status code: " + pr.ExitCode);
return pr.ExitCode;
}
else
{
pr.CancelOutputRead();
pr.CancelErrorRead();
__logger.Debug("Timeout while waiting for execution to finish");
pr.Kill();
return -100;
}

Replace Thread.Sleep with System.Threading.Timer?

I'm trying to replace Thread.Sleep with System.Threading.Timer, and I'm trying to implement it in the following code. The main reason for changing is that, even though it works when testing locally, it's not working properly in the server. Plus, I've read that using it here is bad practice.
I've seen several examples (including the one below), but I'm not certain how I could use it in my case: System.Threading.Timer in C# it seems to be not working. It runs very fast every 3 second
In my console app, I need to copy files to our server every 15 minutes. So at :20, :35, :50, :05, I begin reading files for that quarter. In the case below, the files will be available at :45, and I add 5 minutes just in case.
This is my code. I had previously tried to copy files from several quarters in parallel, but the server where the source files reside is having trouble with that. So I'm going back to this.
My question is, how can I replace Thread.Sleep with System.Threading.Timer in this example?
I wanted to try await Task.Delay(Int32), but I have VS2010:
DateTime lastTimeRead = new DateTime(2014, 9, 9, 8, 35, 0); //Last read at 8:35AM
DateTime nextTimeRead;
for (; ; )
{
now = DateTime.Now; //It's currently 8:43AM
nextTimeRead = LastTimeRead.AddMinutes(15); // nextTimeRead = 8:50AM.
if (nextTimeRead > now) //Yes, so wait 7 minutes for files to be available
{
TimeSpan span = nextTimeRead.Subtract(now);
Double milliseconds = span.TotalMilliseconds;
Console.WriteLine("Sleep for milliseconds: " + milliseconds.ToString());
Thread.Sleep(Convert.ToInt32(milliseconds));
Console.WriteLine("Download files after sleep of: " + nextTimeRead.ToString());
DownloadFilesByPeriod(nextTimeRead);
}
else // Files are available. Read.
{
Console.WriteLine("Download files no sleep: " + nextTimeRead.ToString());
DownloadFilesByPeriod(nextTimeRead);
}
LastTimeRead = nextTimeRead;
}
The idea is to have a timer and Enable it when you want to set the delay in your program:
System.Timers.Timer Delay = new System.Timers.Timer();
Delay.Elapsed += new System.Timers.ElapsedEventHandler(Delay_Elapsed);
Delay.Interval=Convert.ToInt32(milliseconds);
Delay.Enabled = false;
void Delay_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Delay.Enabled = false;
}
......
.....
if (nextTimeRead > now) //Yes, so wait 7 minutes for files to be available
{
TimeSpan span = nextTimeRead.Subtract(now);
Double milliseconds = span.TotalMilliseconds;
Console.WriteLine("Sleep for milliseconds: " + milliseconds.ToString());
Delay.Enabled = true;
while (Delay.Enabled)
{
////Wait until time passes
}
Console.WriteLine("Download files after sleep of: " + nextTimeRead.ToString());
DownloadFilesByPeriod(nextTimeRead);
}

Azure WebJob Command Timeout

We are having issue with Azure Web Jobs. We created a C# console application, zipped it, and created the new Web Job. It's a c# console app that will constantly hit one of our web services to process items in queue.
Whenever we run the Web Job, we are getting the following error:
'cmd /c xxxxxxxx....' aborted due to no output and CPU activity for
121 seconds. You may increase SCM_COMMAND_IDLE_TIMEOUT setting to
solve the issue
When we increased the SCM_COMMAND_IDLE_TIMEOUT to 600 (10 minutes). The job DOES run for 10 minutes - and then we get the same error with the same 121 seconds error.
What are we doing wrong?
Here is the console app code:
static void Main(string[] args)
{
bool ThereAreItemsInQueue = true;
int Counter = 1;
DateTime StartTime = DateTime.Now;
while(ThereAreItemsInQueue)
{
Task.Run(() => {
try
{
//DEQUEUE
byte[] response = HttpHelper.HttpPOST(#"xxxxxxxxxxxxx", new byte[0]);
string strResponse = System.Text.Encoding.Default.GetString(response);
System.Diagnostics.Trace.TraceError("Attempt #" + Counter + "DEQUEUE FINISHED. Response:" + strResponse);
//CHECK IF THE QUEUE IS EMPTY
if (strResponse.Contains("Were Done"))
ThereAreItemsInQueue = false;
}
catch(Exception ex)
{
System.Diagnostics.Trace.TraceError("Error Has Occured on attempt #" + Counter + "." + ex.Message + "\r" + ex.StackTrace);
}
});
System.Threading.Thread.Sleep(5000);
//SEE IF THIS HAS BEEN RUNNING FOR MORE THAN 24 HOURS
if (DateTime.Now.Subtract(StartTime).TotalHours >= 24)
ThereAreItemsInQueue = false;
Counter++;
}
}
Are we approaching this problem the wrong way?
Note: each HttpHelper.HttpPOST request takes about 2 seconds - so that's not the issue.
Note2: We are using Task.Run to create "set-it-and-forget-it" type of requests.
Note3: The website setting of "Always On" - is turned on.
For triggered WebJobs the way to increase idle timeout is using the app setting: WEBJOBS_IDLE_TIMEOUT. Set it to your desired timeout in seconds.
The error is confusing and only refers to idle timeout during deployment.
https://github.com/projectkudu/kudu/wiki/Web-jobs#configuration-settings
This seems to have solved my problem:
if (Counter % 25 == 0)
Console.WriteLine("Heartbeat");
I guess you have to keep writing out to console to keep the JOB running.

Workflows works slowly

I have a problem with workflow. I use "State Machine Workflow" in project. Over time more and more workflow created, and application works slowly. After restart project application works normal, but after some time application works slowly again
Maximum working thread counts
int maxThreadinCore;
if (!int.TryParse(ConfigurationManager.AppSettings["MaxThreadWorkflow"], out maxThreadinCore))
maxThreadinCore = 5;
LogAdapter.Instance().LogInfo("Config max Thread" + maxThread);
var maxThreadCount = maxThreadinCore;
if (Environment.ProcessorCount != 1)
{
maxThreadCount = (int)((maxThreadinCore* Environment.ProcessorCount) * .8);
}
var scheduler = new DefaultWorkflowSchedulerService(maxThreadCount);
When created a lot of workflow
while (loadedWorkfolows.Count > MaxThreads || totalMem > 1073741824)
{
Thread.Sleep(1000);
loadedWorkfolows = _runtime.GetLoadedWorkflows();
GC.Collect();
totalMem = GC.GetTotalMemory(false);
}
This code is to be completed only in the case when there are no free workflows and we are waiting for new workflows.
If we will delete this code the workflows will be created while the system will be off free workflows and we will get the message AvailableThreads = 0
while (avlThreads < 10)
{
LogHelper.Instance().Log(LogLevel.Debug,
string.Format("AvailableThreads = {0}", avlThreads));
ThreadPool.GetAvailableThreads(out avlThreads, out avlPort);
Thread.Sleep(1000);
}
When I set MaxThreads to 100, application use 100 loaded workflow and it works quickly enough. But after some time workflow begin to work slowly and I need to restart the service
Please advice me if somebody had a similar problem

Categories