What's the best way if you have a big script with a large process and you get an Error, then how to tell the script, wait 1min and begin again from top.
It's written in asp.net, c#.
Example
protected void doAll() {
FirstFunction();
// If I get in this function an error it should stop wait 1min. and start doAll() again.
NextFunction();
// END
}
Try the code that may cause an error inside FirstFunction(). Catch the resulting error, sleep for a minute and call doAll(). I am not sure how it is done in ASP.NET/C#.
Think about what you are saying. Do you really want the user to wait 1, 2, 3 or even more minutes for a web page to download and render on their screen?
I strongly suggest you think about some other way of handling errors in this routine. Perhaps if you explained to us why you want to wait 1 minute, we might be able to suggest a better approach.
Related
I am attempting to send an image to the browser every 16 ms (~60Hz) from a specific file on the drive which is changing constantly (also at ~60Hz). To do this I am using Response.BinaryWrite(). Below is my code (it really is quite simple)
protected void Page_Load(object sender, EventArgs e)
{
MainLoop();
}
private async Task MainLoop()
{
while (true)
{
//Update image to latest from server
Response.ContentType = "image/png";
Response.BinaryWrite(File.ReadAllBytes(Server.MapPath("/Frames/frame.png")));
Response.Flush();
await Task.Delay(16);
}
}
My problem is that it does not refresh. I have double and triple checked that the file is indeed changing, and I have also tried updating a label with the current time in milliseconds. I have found that even when doing that, it does not update at all after the page loads.
If I reload the page it displays both a new image, and a new time, so the issue doesn't seem to be in the Response writing. Rather, it's as if the page is simply ignoring the loop entirely, and only running once through.
If anybody has any advice on alternatives to try (keep in mind video is not an option due to the live nature of this) I would be glad to hear them. Perhaps I am missing something very simple here, but I just can't find it!
Thanks!
Thoughts on the problem:
So the problem is that the page doesn't render updated results every 16ms. We can't solve this issue through server side code (e.g. c# code like your snippet).
I'm sure the while loop is still running but you will always need to refresh the page manually since this is ASP.NET (traditional web app with refresh). Here is a stack overflow answer that can back me up (in case you are skeptical about what I'm saying) refresh page after 3 seconds using c#
I'm not sure what the end goal here is, but I'm assuming you want to render your page with your updated png every 16ms. Basically from my 2 points above, don't resort to trying to update the image through the server side; instead, look into other options through the client side code (e.g. javascript).
Of course, I would try to comment further on where you should look exactly, but I never really dealt with updating an image every 16ms before!
I'm just going to throw in some links that could generate some ideas:
Refresh an image in the browser every x milliseconds
Change image in HTML page every few seconds
http://www.labbookpages.co.uk/web/realtime.html
I hope this can push you along! Let me know how this goes because I'm curious on how you will do this :)
You need to not only get the new image but also ensure the browser does not use the cashed image.
So, there's four steps to the solution:
Create a controller action that returns the current image, but your controller action needs to take an argument. The argument becomes a query string parameter. Each time you call the method, the param value should be different. This way, the browser considers the URL to be new and will not use a cached image. Your url should look something like http://mysite/my controller/getimage?param=12345678927483817
Create a JavaScript method to change the SRC property of the image by pointing it to the URL of your new controller action. Use something that constantly changes for your query parameter. I suggest using the current date time in milliseconds.
After the page loads, set a timer in JavaScript to call the function you created in Step 2.
Eat a cookie, because cookies are good.
I have an input box that pulls an autocomplete list. The list is a little slow to pull, so I need selenium to just wait before pressing the enter key, which will select the first item in the list. here is what I have so far
webDriver.FindElement(By.Id("seg-gl-1")).SendKeys("2");
webDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
webDriver.FindElement(By.Id("seg-gl-1")).SendKeys(Keys.Enter);
The issue is that selenium is hitting Enter too quickly. I believe I am using the implicitwait incorrectly. Can anyone shed some light on my issue?
When you use
webDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
You are only setting the default ImplicitWait time. If you want to actually perform a wait for, lets say 10sec, you could use
System.Threading.Thread.Sleep(5000);
Generally you should avoid this type of wait, but I'm guessing that there are javascript/ajax calls performed in the background of your application, and hence you should wait for these to execute before being able to assert the site behaviour (as these calls might update the DOM and such). For further help on that, please refer to my answer in this thread: https://stackoverflow.com/a/45033412/6220192
For testing reasons I want to be able to adjust what time Quartz.Net currently thinks it is so I do not necessarily have to wait hours, days, or weeks in order to check that my code is working.
For this purpose I created the following simple function (it is in F# but could be easily be done in C# or another language) :
let SimulateTime = fun () ->
currentTime <- DateTimeOffset.UtcNow
timeDifferenceInSeconds <- (currentTime - lastCheckedTime).TotalSeconds
simulatedTime <- simulatedTime.AddSeconds((timeDifferenceInSeconds *scaleTimeBy))
lastCheckedTime <- currentTime
simulatedTime
Where currentTime, lastCheckedTime, and simulatedTime would all be of type DateTimeOffset and both timeDifferenceInSeconds and scaleTimeBy are of type float.
I then change SystemTime.Now and SystemTime.UtcNow to use the above function as follows :
SystemTime.Now <-
Func<DateTimeOffset>(
fun () -> SimulateTime())
SystemTime.UtcNow <-
Func<DateTimeOffset>(
fun () -> SimulateTime())
Which was shown by Mark Seemann in a previous question of mine that can find here.
Now this mostly works except it seems like the longer function causes it to be off by a decently wide margin. What I mean by this is that all of my triggers will misfire. For example if I have a trigger set to occur every hour and set scaleTimeBy to 60.0 so that every second passed counts as a minute, it will never actually trigger on time. If I have a misfire policy, the trigger can then go off but the time it lists for when it activated will be as late as the half hour mark (so takes a full 30 seconds slower than what it should have been in this example).
However I can do this :
Console.WriteLine(SimulateTime())
Thread.Sleep(TimeSpan.FromSeconds(60.0))
Console.WriteLine(SimulateTime())
And the difference between the two times output to the screen in this example will be exactly an hour so the call doesn't seem like it should be adding as much of a time difference than it does.
Anyone have any advice on how to fix this issue or a better way of handling this problem?
Edit :
So the C# version of the SimulateTime function would be something like this :
public DateTimeOffset SimulateTime() {
currentTime = DateTimeOffset.UtcNow;
double timeDifference = (currentTime - lastCheckedTime).TotalSeconds;
simulatedTime = simulatedTime.AddSeconds(timeDifference * scaleTimeBy);
lastCheckedTime = currentTime
return simulatedTime;}
If that helps anyone with solving this problem.
So this issue is misfires caused by the fact that Quartz.net will idle and wait when it thinks it doesn't have any triggers occurring any time soon to avoid making too many calls. By default it waits about 30 seconds give or take if it doesn't have any triggers occurring in the time span. The idleWaitTime variable is a Timespan set in the QuartzSchedulerThread. Now when checking for triggers that might occur soon it also uses the BatchTimeWIndow from QuartzSchedulerResources.
Both idleWaitTime and BatchTimeWindow can be set in configuration/properties files where they'd be called "org.quartz.scheduler.idleWaitTime" and "org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow."
Based off what it is called in BatchTimeWindow I thought it was just a bit of look ahead for grabbing a variable (which would like since if I'm speeding things up, I'd want a small idleWaitTime but I would want it to look further ahead for triggers because the few seconds your waiting is actually minutes so will trigger sooner than it thinks), but the description of "org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow" on pages going over configuration properties implies that it can cause things to fire early and be less accurate. So to start here is the code for just modifying idleWaitTime
let threadpool = Quartz.Simpl.SimpleThreadPool()
let jobstore = Quartz.Simpl.RAMJobStore()
let idleWaitTime = TimeSpan.FromSeconds(30.0/scaleTimeBy)
let dbfailureretryinverval = TimeSpan(int64 15000)
Quartz.Impl.DirectSchedulerFactory.Instance.CreateScheduler("TestScheduler","TestInstance",threadpool,jobstore,idleWaitTime,dbfailureretryinverval)
let scheduler = Quartz.Impl.DirectSchedulerFactory.Instance.GetScheduler("TestScheduler")
You can create a Scheduler that has the idleWaitTime you want by using the DirectSchedulerFactory which probably could use a little bit better documentation. It takes also a bunch of stuff you may or may not want to modify depending on what you are working on. For threadpool I just use Quartz.net's default SimpleThreadPool because I do not care about messing with the threading at this time and would not want to explain how you go about doing so unless that was the whole point of the question. Information on jobstores is available here. I am using RAMJobStore here because it is simpler than AdoJobStore but it shouldn't matter for this example. The dbfailureretryinterval is another value that don't care about for this example so I just looked up what it is set to by default. Its value should matter the least for this example because not connecting to a database. For idleWaitTime might want to do more tests to figure out what is a good value for it, but I chose to go with just scaling its default value of 30 seconds by scaleTimeBy since that is what I'm using to scale how fast things are going by. So this should make it so if I am having the program simulate time going by at a much faster rate, then it should only remain idle for smaller periods of time. One important thing to note is that when create a scheduler in this way, it is not returned as well so need to make a separate call to get the scheduler I just created. I have no idea why this is this way, I'm guessing that if you are creating several Schedulers and not necessarily using all of them it is better this way.
Now after all that you are likely to still get a bit of a misfire rate. While it is now idling for much smaller units of time (only a few seconds so potentially an acceptable margin depending on what your use case is), it still has the issue of it is only then checking to see if it has a coming trigger in the next few fractions of a second.
So lets see if adding time to BatchTimeWindow helps matters?
let threadpool = Quartz.Simpl.SimpleThreadPool()
let threadexecutor = Quartz.Impl.DefaultThreadExecutor()
let jobstore = Quartz.Simpl.RAMJobStore()
let schedulepluginmap = System.Collections.Generic.Dictionary<String,Quartz.Spi.ISchedulerPlugin>()
let idleWaitTime = TimeSpan.FromSeconds(30.0/timeScale)
let maxBatchSize = 1
let batchTimeWindow = TimeSpan.FromSeconds(timeScale)
let scheduleexporter = Quartz.Simpl.RemotingSchedulerExporter()
Quartz.Impl.DirectSchedulerFactory.Instance.CreateScheduler("TestScheduler","TestInstance",threadpool,threadexecutor,jobstore,schedulepluginmap,idleWaitTime,maxBatchSize,batchTimeWindow,scheduleexporter)
let scheduler = Quartz.Impl.DirectSchedulerFactory.Instance.GetScheduler("TestScheduler")
Now this has even more variables that don't really care about for the purposes of this example and won't even bother going over because adjusting batchTimeWindow actually makes it worse. Like getting you back to misfiring by 30 minutes. So no, batchTimeWindow while looks like might be useful is not. Only modify idleWaitTime.
Ideally for this use would want a small wait time and a larger look ahead time, but the option for that does not seem like its available.
I am trying to create a script which does something say show a popup after 1 day. As far as I know I can do this using Thread.Stop or using System.Timers or many other ways. But the problem with each is that the computer has to be continuously running for each of these methods to give desired result at the time I want. Basically I want the script to start with installation of my program, wait for exactly 24 hours, then display a message box. If the computer is switched on at that time i.e. after 24 hours it should show the message box on next start up but only if 24 hours or more have passed. Please help, i am unable to find suitable solution for this. any help will be highly appreciated. I think that it may be achieved by getting the dateTime.Now and putting it in a file, and then compare current system time to the time in file every hour or so, and if 24 hours or more have passed, show the message box. Please help
If a message box is what you need to pop up, then you'll need a Windows Forms application. Here is the workflow of how it'll work:
Application will need to save data, either through a database or to a file.
When the application first loads, it will check either the database or the file for a TriggerDate entry.
If the TriggerDate exists, pull this date and compare it to today's date and time. If the current date and time is past our TriggerDate, display the message box. Recreate the TriggerDate with the current date and time plus 24 hours.
If TriggerDate does not exist, create it, filled with the current date and time plus 24 hours (e.g. DateTime.Now.AddHours(24)).
Use Threading.Thread.Sleep() to sleep for 5 minutes.
Jump to step 3 and repeat.
EDIT
Code will be something like this:
private const string TriggerFile = #"C:\TriggerData\trigger.txt";
private DateTime _triggerDate;
if (!File.Exists(TriggerFile))
{
using (StreamWriter sw = File.CreateText(TriggerFile))
{
sw.WriteLine(DateTime.Now.AddHours(24));
}
}
using (StreamReader sr = File.OpenText(TriggerFile))
{
_triggerDate = DateTime.Parse(sr.ReadToEnd());
}
while (true)
{
if (DateTime.Now >= _triggerDate)
{
MessageBox.Show(#"Alert!");
using (StreamWriter sw = File.CreateText(TriggerFile))
{
sw.WriteLine(DateTime.Now.AddHours(24));
_triggerDate = DateTime.Now.AddHours(24);
}
}
System.Threading.Thread.Sleep(60000*5); // Sleep for 5 minutes
}
You may not want to do while(true). You way want to implement a way to get out of the program.
If I understand correctly, what you can use is a way to save the "start date". You can save the start date of the timer and read the value from your script, that way you can calculate if 24 hours or more has passed since the moment you assigned a value to the start date. You can use a simply TXT file to save the value.
I see two ways of achieving this :
Easy way (but not strictly related to C#) is to use the task scheduler and create a task that will run your C# program every 24 hours. One way to do this from an installer would be to use the SchTasks.exe tool. This method allows you to just exit the program after your work is done without having to explicitely wait for the next run.
Harder way: Create a Windows Service, which is a program specifically designed to run permanently on the host computer. These programs are slightly more technical to write though. You can find more explanations about services here. However, you may not want to take this route as service cannot display user interfaces like popups.
Update: The answers from Andrew and Conrad were both equally helpful. The easy fix for the timing issue fixed the problem, and caching the bigger object references instead of re-building them every time removed the source of the problem. Thanks for the input, guys.
I'm working with a c# .NET API and for some reason the following code executes what I feel is /extremely/ slowly.
This is the handler for a System.Timers.Timer that triggers its elapsed event every 5 seconds.
private static void TimerGo(object source, System.Timers.ElapsedEventArgs e)
{
tagList = reader.GetData(); // This is a collection of 10 objects.
storeData(tagList); // This calls the 'storeData' method below
}
And the storeData method:
private static void storeData(List<obj> tagList)
{
TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
long timestamp = (long)t.TotalSeconds;
foreach (type object in tagList)
{
string file = #"path\to\file" + object.name + ".rrd";
RRD dbase = RRD.load(file);
// Update rrd with current time timestamp and data.
dbase.update(timestamp, new object[1] { tag.data });
}
}
Am I missing some glaring resource sink? The RRD stuff you see is from the NHawk C# wrapper for rrdtool; in this case I update 10 different files with it, but I see no reason why it should take so long.
When I say 'so long', I mean the timer was triggering a second time before the first update was done, so eventually "update 2" would happen before "update 1", which breaks things because "update 1" has a timestamp that's earlier than "update 2".
I increased the timer length to 10 seconds, and it ran for longer, but still eventually out-raced itself and tried to update a file with an earlier timestamp. What can I do differently to make this more efficient, because obviously I'm doing something drastically wrong...
Doesn't really answer your perf question but if you want to fix the rentrancy bit set your timer.AutoRest to false and then call start() at the end of the method e.g.
private static void TimerGo(object source, System.Timers.ElapsedEventArgs e)
{
tagList = reader.GetData(); // This is a collection of 10 objects.
storeData(tagList); // This calls the 'storeData' method below
timer.Start();
}
Is there a different RRD file for each tag in your tagList? In your pseudo code you open each file N number of times. (You stated there is only 10 objects in the list thought.) Then you perform an update. I can only assume that you dispose your RRD file after you have updated it. If you do not you are keeping references to an open file.
If the RRD is the same but you are just putting different types of plot data into a single file then you only need to keep it open for as long as you want exclusive write access to it.
Without profiling the code you have a few options (I recommend profiling btw)
Keep the RRD files open
Cache the opened files to prevent you from having to open, write close every 5 seconds for each file. Just cache the 10 opened file references and write to them every 5 seconds.
Separate the data collection from data writing
It appears you are taking metric samples from some object every 5 seconds. If you do not having something 'tailing' your file, separate the collection from the writing. Take your data sample and throw it into a queue to be processed. The processor will dequeue each tagList and write it as fast as it can, going back for more lists from the queue.
This way you can always be sure you are getting ~5 second samples even if the writing mechanism is slowed down.
Use a profiler. JetBrains is my personal recommendation. Run the profiler with your program and look for the threads / methods taking the longest time to run. This sounds very much like an IO or data issue, but that's not immediately obvious from your example code.