Workflows works slowly - c#

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

Related

Increasing a timer everytime an evaluation is false

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;

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.

Start an offline ClickOnce Application and wait for Exit

I have deployed a ClickOnce Windows Forms application (App A)
Another application (App B) starts App A with a filename as parameter.
I do this with this Code
var basePath = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
var location = String.Format(#"{0}\{1}\{2}\{3}",
basePath, "MyCompany", "MyProduct", "MyApp.appref-ms");
var fileName = #"c:\temp\somefile.ext";
var uri = new Uri(fileName).ToString();
Process.Start(location, uri);
App A grabs the file name from AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData[0] and show the content.
This works like a charm. However, now I want App B to wait for App A to exit.
But a call to Process.WaitForExit() returns instantly.
Is there a way to open a ClickOnce App and wait for it to exit? I can, if necessary, change the way the app is opend but the requirement is that I need to run the app as a ClickOnce app (I know that somewhere in my user profile AppData\Local\Apps\2.0\ folder the exe exists and can be started directly but If I do that ApplicationDeployment.IsNetworkDeployed is false and ApplicationDeployment.CurrentDeployment is null. In that I loose the ClickOnce Update Capabilities).
my suggestion would be to use Mutex in App A, and let App B check and wait for it. This is the cleanest way from my point of view.
App A does this when starts:
private static Mutex mutex;
public static void Main()
{
// if you want your app to be limited to a single instance
// across ALL SESSIONS (multiple users & terminal services), then use the following line instead:
// string mutexName = string.Format("Global\\{0}", ProgramInfo.AssemblyGuid);
var mutexName = string.Format("Local\\{0}", SOME_SHARED_GUID);
mutex = new Mutex(true, mutexName, out singleInstance);
if (singleInstance == false)
{
// that means your app has more than one instance running
// you need to decide what to do here.
}
// rest of initialization code
Application.Run();
// release the mutex so App B can continue
mutex.ReleaseMutex();
}
and App B just waits for the mutex to be released:
Process.Start(location, uri);
Thread.Sleep(5000); // give it 5 seconds or so to check for updates and start
var mutexName = string.Format("Local\\{0}", SOME_SHARED_GUID);
mutex = new Mutex(false, mutexName);
mutex.WaitOne();
The problem is that starting the appref-ms process does not actually start the application it starts the deployment manifest, which then launches the application itself, so the process you are starting exits straight away.
You can add a check to see when you application has started if you know the name (which I assume you do) like this:
string myAppName = "YourAppName";
DateTime startTime = DateTime.Now;
int newProcessId = 0;
List<int> runningProcessIds = new List<int>();
//find all the running processes and record their Ids
foreach (void proc_loopVariable in Process.GetProcessesByName(myAppName)) {
proc = proc_loopVariable;
runningProcessIds.Add(proc.Id);
}
//start the new process
Process.Start(location);
//wait for the new application to be started
while (!(Process.GetProcessesByName(myAppName).Count != runningProcessIds.Count)) {
//timeout if we have not seen the application start
if ((DateTime.Now - startTime).TotalSeconds > 30)
break;
}
//loop through all the running processes again to find the id of the one that has just started
foreach (void proc_loopVariable in Process.GetProcessesByName(myAppName)) {
proc = proc_loopVariable;
if (!runningProcessIds.Contains(proc.Id)) {
newProcessId = proc.Id;
break;
}
}
//wait for the application to finish
Process.GetProcessById(newProcessId).WaitForExit();
Debug.WriteLine("Finished");

Track dead WebDriver instances during parallel task

I am seeing some dead-instance weirdness running parallelized nested-loop web stress tests using Selenium WebDriver, simple example being, say, hit 300 unique pages with 100 impressions each.
I'm "successfully" getting 4 - 8 WebDriver instances going using a ThreadLocal<FirefoxWebDriver> to isolate them per task thread, and MaxDegreeOfParallelism on a ParallelOptions instance to limit the threads. I'm partitioning and parallelizing the outer loop only (the collection of pages), and checking .IsValueCreated on the ThreadLocal<> container inside the beginning of each partition's "long running task" method. To facilitate cleanup later, I add each new instance to a ConcurrentDictionary keyed by thread id.
No matter what parallelizing or partitioning strategy I use, the WebDriver instances will occasionally do one of the following:
Launch but never show a URL or run an impression
Launch, run any number of impressions fine, then just sit idle at some point
When either of these happen, the parallel loop eventually seems to notice that a thread isn't doing anything, and it spawns a new partition. If n is the number of threads allowed, this results in having n productive threads only about 50-60% of the time.
Cleanup still works fine at the end; there may be 2n open browsers or more, but the productive and unproductive ones alike get cleaned up.
Is there a way to monitor for these useless WebDriver instances and a) scavenge them right away, plus b) get the parallel loop to replace the task segment immediately, instead of lagging behind for several minutes as it often does now?
I was having a similar problem. It turns out that WebDriver doesn't have the best method for finding open ports. As described here it gets a system wide lock on ports, finds an open port, and then starts the instance. This can starve the other instances that you're trying to start of ports.
I got around this by specifying a random port number directly in the delegate for the ThreadLocal<IWebDriver> like this:
var ports = new List<int>();
var rand = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
var driver = new ThreadLocal<IWebDriver>(() =>
{
var profile = new FirefoxProfile();
var port = rand.Next(50) + 7050;
while(ports.Contains(port) && ports.Count != 50) port = rand.Next(50) + 7050;
profile.Port = port;
ports.Add(port);
return new FirefoxDriver(profile);
});
This works pretty consistently for me, although there's the issue if you end up using all 50 in the list that is unresolved.
Since there is no OnReady event nor an IsReady property, I worked around it by sleeping the thread for several seconds after creating each instance. Doing that seems to give me 100% durable, functioning WebDriver instances.
Thanks to your suggestion, I've implemented IsReady functionality in my open-source project Webinator. Use that if you want, or use the code outlined below.
I tried instantiating 25 instances, and all of them were functional, so I'm pretty confident in the algorithm at this point (I leverage HtmlAgilityPack to see if elements exist, but I'll skip it for the sake of simplicity here):
public void WaitForReady(IWebDriver driver)
{
var js = #"{ var temp=document.createElement('div'); temp.id='browserReady';" +
#"b=document.getElementsByTagName('body')[0]; b.appendChild(temp); }";
((IJavaScriptExecutor)driver).ExecuteScript(js);
WaitForSuccess(() =>
{
IWebElement element = null;
try
{
element = driver.FindElement(By.Id("browserReady"));
}
catch
{
// element not found
}
return element != null;
},
timeoutInMilliseconds: 10000);
js = #"{var temp=document.getElementById('browserReady');" +
#" temp.parentNode.removeChild(temp);}";
((IJavaScriptExecutor)driver).ExecuteScript(js);
}
private bool WaitForSuccess(Func<bool> action, int timeoutInMilliseconds)
{
if (action == null) return false;
bool success;
const int PollRate = 250;
var maxTries = timeoutInMilliseconds / PollRate;
int tries = 0;
do
{
success = action();
tries++;
if (!success && tries <= maxTries)
{
Thread.Sleep(PollRate);
}
}
while (!success && tries < maxTries);
return success;
}
The assumption is if the browser is responding to javascript functions and is finding elements, then it's probably a reliable instance and ready to be used.

Categories