Using a C# Timer for regular events in ASP.NET - c#

I am working with an ASP site which requires a "reminder" email to be sent out every x, y and z minutes. I have attempted to start a timer upon an event (like a button click or page load) but this proved to be unreliable as the timers would be disposed of when the server performed an automatic backup or when the aspx.cs file was updated.
My new idea is to have a timer constantly running (a check is performed on a page load which ensures its running) and, when it elapses, it checks to see if either x, y or z minutes have elapsed. So if y elapses, it needs to send out a "reminder" email and then restart y's timer.
void ParentTimer_Elapsed(object sender, ElapsedEventArgs e)
{
foreach(Timer childTimer in ChildTimerList)
{
if(childTimer.Enabled == false) // And therefore has elapsed
{
sendReminderEmail(childTimer);
childTimer = checkAndSetCorrectInterval(childTimer);
childTimer.AutoReset = false;
childTimer.Enabled = true;
}
}
}
The list ChildTimerList would obviously contain x, y and z.
Can anybody forsee me running into any problems with this, or are there any better ways to approach it? My perfect solution would be a timer running costantly which doesn't need to be started upon an event but I don't think this is possible with ASP.
Furthermore, where should I initialise my parent timer and childlist variables? In a class within the App_Code folder or, statically, in a code-behind aspx.cs page?
Thanks in advance.
EDIT:
Yes, I do mean ASP.NET... :)

I would probably implement this with a simple console application (responsible for sending e-mails) and Task Scheduler in Windows (responsible for running the application on a schedule). Keep it simple. And robust.
Edit: Provided that you are in control of the server - it will probably not be the best solution in a shared hosting environment where you're only allowed to run web apps.

Related

C# WPF Machine-Dependent Concurrency Issues

I have a multi-threaded C# WPF application that is a plug-in to a larger software (Princeton Instruments LightField, for those who are interested).
My plug-in invokes a synchronous method on a thread separate from the GUI. This method is from a camera API and captures an n-second exposure from the camera and returns the frame that was captured.
The situation looks something like this:
private static volatile bool _STOP = true;
// Runs when the "Run" button is clicked
private void Run_Click(object sender, RoutedEventArgs e)
{
object time = InputTime.Text; // a non-negative integer provided by the user
_STOP = false;
Thread run_thread = new Thread(Running);
run_thread.Start(time);
}
// Runs when the "Stop" button is clicked
private void Stop_Click(object sender, RoutedEventArgs e)
{
_STOP = true;
}
// Separate Thread from GUI
private void Running(object t)
{
int time = Convert.ToInt32(t);
FrameObject f;
while(!_STOP)
{
// synchronously capture a t-second exposure
f = CameraAPI.CaptureImage(t);
// display the exposure on a viewer controlled by the parent thread
Application.Current.Dispatcher.BeginInvoke(new Action(Viewer.Display(f));
}
}
This code (or, rather, it's more complex sibling) works perfectly fine on the computer I developed it on (Computer A). I click Run and the entire application remains responsive while the code is running.
When I try to run it on the computer where it will be hosted regularly (Computer B), however, the following behavior appears:
When clicking the Run button, the GUI becomes unresponsive for n
seconds (n being the time sent to the CameraAPI.CaptureImage(n);
method). This occurs for any positive integer n and continues as the
while loop executes this method each loop cycle (i.e. the application freezes for n seconds, there is a brief unfrozen moment while the Display method is called, and then the application freezes again for n seconds).
If I call Thread.Sleep(n); in place of
CameraAPI.CaptureImage(n);, the application does not freeze.
It is not just my plug-in that freezes - it is the entire application.
I have built, rebuilt, deleted and recopied my code from Computer A to Computer B, and the error persists.
Computer A (where I built this) is identical (as far as I've found)
to the computer having the issues (Computer B). The processors, OS,
drives, RAM, application versions, etc. are all the same. Computer A
specifically exists so that applications can be developed for
Computer B.
Removing the Application.Current.Dispatcher.BeginInvoke(new Action(Viewer.Display(f)); line does not stop the GUI freezing. This is not the problem method.
The application uses the same number of threads (43) on each computer. When the plug-in is running, the number of threads increments by the same amount (1-4 depending on where in the program we are) on each computer.
So, on two seemingly identical systems, the same code has different results. On System A, it works as intended (no GUI freezing), and on System B, the GUI of the entire application -- not just of the plug-in that I am writing -- freezes each time a synchronous method is called.
This error behavior exceeds my understanding of computers, so now I'm here. Any ideas as to what is causing this difference in behavior?
We reinstalled the parent application and everything works fine. Still have no idea why this happened, but closing the question since the problem is resolved. A true case of "turn it off and back on again."

Inactivity and activity ,application idle , user-inactivity auto logout

After lot of googling and spending 4 hours I guess this is the best way to find user inactive and lock screen.
public MainWindow()
{
InitializeComponent();
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(10) };
timer.Tick += delegate
{
timer.Stop();
MessageBox.Show("Logoff trigger");
timer.Start();
};
timer.Start();
InputManager.Current.PostProcessInput += delegate(object s, ProcessInputEventArgs r)
{
if (r.StagingItem.Input is MouseButtonEventArgs || r.StagingItem.Input is KeyEventArgs)
timer.Interval = TimeSpan.FromSeconds(10);
};
}
If your question is, "Is there a better way to implement a session timeout?" - then I would say, possibly - this is how I do it.
A session timeout can do one of two things. It can work like an arcade game where you have a timeout duration in which to complete your tasks. Or it can monitor for inactivity and close if nothing happens.
Either way, I would wrap this functionality into a session provider - assuming MVVM is the goal, I use provider to refer to a service or data source of some sort.
The provider gets instantiated as a singleton and so exists as one instance throughout the app life cycle. I usually manage this by creating it in app.xaml. I then interact with the provider using a message framework such as MVVM light.
Once created the provider manages a thread which checks a datetime to see if it occurs in the past. If it does it issues a session over event or message. This message is picked up by your application to shut down or whatever.
If you want a finite period or time, you implement a start message which sets the monitored date time to a point in the future according to the time span you want to run. If you want an inactivity log out then you send this message from whatever user interactions you see fit to prevent log out such as input changes or ICommand executes.
I take this a stage further so my provider also issues an 'ending' message a few seconds before the timeout completes so I can display a warning - but hopefully you get the general idea.
If this sounds like what you're after then I will add in some examples, but haven't so far in case this is not what you're asking.

Problems getting newly created thread to send outputs to asp:panel in ASP.NET C#

I'm creating a file processor for use in an intranet.
I described it in another question - ERR_EMPTY_RESPONSE when processing a large number of files in ASP.Net using C#
Now, as suggested on above question's answer, I'm trying to use threads to execute the file processing task.
But there is a problem. I need the newly created thread to write feedbacks to a component in page (asp:panel, or div, or whatever). Those feedbacks would be results from several database operations.
The application reads those txts, interprets each line of it, and insert data in database. Each line inserted in database must return a feedback, like "registry 'regname' inserted successfully", or "i got problems inserting registry 'regname' in file 'filename', skipping to next registry".
I did test with something very simple:
protected void DoImport()
{
try
{
MainBody.Style.Add(HtmlTextWriterStyle.Cursor, "wait");
int x = 0;
while (x < 10000)
{
ReturnMessage(String.Format("Number {0}<hr />", x), ref pnlConfirms);
x++;
}
}
catch (Exception ex)
{
ReturnMessage(String.Format("<font style='color:red;'><b>FATAL ERROR DURING DATA IMPORT</b></font><br /><br /><font style='color:black;'><b>Message:</b></font><font style='color:orange;'> {0}</font><br />{1}", ex.Message, ex.StackTrace), ref pnlErrors);
}
finally
{
MainBody.Style.Add(HtmlTextWriterStyle.Cursor, "default");
}
}
This function is called from Page_Load, and fills an asp:panel called "pnlConfirms" with a row of numbers, but all at once, on load.
I changed it to:
protected void DoImport()
{
try
{
MainBody.Style.Add(HtmlTextWriterStyle.Cursor, "wait");
ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork));
}
catch (Exception ex)
{
ReturnMessage(String.Format("<font style='color:red;'><b>FATAL ERROR DURING DATA IMPORT</b></font><br /><br /><font style='color:black;'><b>Message:</b></font><font style='color:orange;'> {0}</font><br />{1}", ex.Message, ex.StackTrace), ref pnlErrors);
}
finally
{
MainBody.Style.Add(HtmlTextWriterStyle.Cursor, "default");
}
}
private void DoWork(Object stateInfo)
{
int x = 0;
while (x < 10000)
{
ReturnMessage(String.Format("Number {0}<hr />", x), ref pnlConfirms);
x++;
}
}
And both uses this function:
public void ReturnMessage(string message, ref Panel panel, bool reset = false)
{
if (reset)
{
panel.Controls.Clear();
}
Label msg = new Label();
msg.Attributes.Add("width", "100%");
msg.Text = message;
panel.Controls.Add(msg);
}
I need ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork)); to fill those asp:panels with feedbacks - like insertion errors and warnings.
My code already has those feedbacks under try...catch statements, but they're not getting output to any asp:panel from threadpool (it works when invoked directly from DoImport() function, like in the first example I posted).
I'm doing something very wrong, but I can't find out what (and I'm researching this for almost 2 weeks). Please, help!
In ASP.NET, when a browser requests a page, that page is rendered and sent to the browser as soon as its processing finishes, so the browser will show the page as it's finally rendered.
According to your code you're trying to render a page, show a wait cursor, and expect it's shown on the browser and then, the cursor is changed by a default cursor. As I explained, independently from using or not additional threads, the page won't be sent to the browser until it's completely rendered. So you'l never see the wait cursor on the client side.
The easiest wait to get what you're trying to do is to use web services (traditional .asmx or WCF) and AJAX (jquery os ASP.NET AJAX).
1) create a web service that does the processing
2) create a page which is sent to the browser, and, using javascript (jQuery or ASP.NET AJAX) make a call to the web service, and show something to let the user know that the request is being processed. (a wait cursor, or even better an animated gif)
3) when the process finishes, your javascript will get the responde from the web service, and you can update the page to let the user know the process has finished.
if you don't have experience on javascript, you can make most of this task using:
ScriptManager which can be used to create a javascript web service proxy for your client side (other interesting article) and is required for the rest of the controls
some javascript (or jquery) which can be use to update the "process running/ process finished hints" on the client side. I.e. when the call to the web service ends, you can use javascript to update the page using DOM, or load a new page or the same page with an special parameter to show the result of the process
In this way you can do what you want:
1) show a page in a state that shows the process is running
2) show the same, or other page, in a state that shows the end of the process
The trick is comunicating the browser with the server, and this can only be done using some of the available ajax techniques.
Another typical technique is using jQuery.ajax, like explained in encosia.com
According to the OP message, the process of all the files would be so slow that it would tiemout the web service call. If this is the case, you can use this solution:
1) Create a web service that process one (or a batch) of the pending files, and returns at least the number of pending files when it finishes the processing of the current file (or batch).
2) from the client side (javascript), call the web service. When it finishes, update the page showing the number of pending files, and, if this number is greater than zero, call the web service again.
3) when the call to the web service returns 0 pending files, you can update the page to show the work is finished, and don't call it any more.
If you process all the files at once, there will be no feedback on the client side, and there will also be a timeout. Besides, IIS can decide to stop the working thread which is making the work. IIS does this for several reasons.
A more reliable solution, but harder to implement, is:
1) implement a Windows Service, that does the file processing
2) implement a web service that returns the number of pending files (you can communicate the Windows Service and Web App indirectly using the file system, a database table or something like that)
3) use a timer (ajax timer, or javascript setInterval) from your web page to poll the server every N seconds using the web service, until the number of pending files is 0.
An even harder way to do this is hosting a WCF service in your Windows Service, instead of the indirect communication between your web app and windows service. This case is much more complicated because you need to use threads to do the work, and attend the calls to the wcf service. If you can use indirect communitacion it's much easier to implemente. The dtabse table is a simple and effective solution: your working process updates a row a table whenever it process a file, and the web service reads the progress state from this table.
There are many different soultions for a not so simple problem.
You are starting new thread (or more precise running your code on one of free threads in thread pool)and not waiting for results in main thread. Something like Thread.Join (if you would use manual thread creation) or other synchronization mechanism as events need to be used if you want to go this route.
The question you've linked to suggests using asynchronous pages which you are not doing. You would start processing request, kick off the task and release the thread, when the task is finished you complete request.
Side note: consider simply doing all conversion on main thread that handles request. Unless you expect slow I/O to complete the task moving CPU work from one thread to another may not produce significant gains. Please measure performance of your current solution and confirm that it does not meet performance goals you have set up for your application. (this does not apply if you doing it for fun/educational purposes).

Monitor web pages access

I hope I can get some help.
I’m trying to create an host based application using C# (in the simplest way) to monitor access to a web page from the computer that hosts the application, if this web page is accessed while the program is running an event should rise.
So far I have used the SHDocVw.ShellWindows() but it works only if the web page has already been accessed not while is being accessed.
It monitors Windows Internet Explorer
I have also researched the httplistener but to no avail.
Do you have any solution?
Please let me know if you require more details
This may or may not be valid for your situation, but I had to do something similar with an Intranet website (cross-browser so it was a little harder than just with IE) recently. My solution was to setup a client-side application which hosts a WCF service. Then, when the user clicks a link on the web page (or raises any event, such as, $(document).ready) it sends an message back to the server telling the server to connect to the IP address associated with the current session (really just the IP Address on the request) on a known port. This connection is made to the client side application which is listening at that IP address and port for instructions on what to do (in my case it is dynamically compiling code in the request and running it).
That of course will only work for Intranet websites. A more general approach that will work for IE across the internet, is to create a IE extension (or maybe a Silverlight application) that talks on localhost. I've never done it, so I can't tell you how or if it is actually possible (but in principle seems possible).
If you don't have access to the website at all then perhaps using SharpPCAP or the Fiddler API would work for you.
Assuming the question is "I want to know when a program on my local computer accesses a give web page": A transparent http proxy is likely approach you want to take. Check out Fiddler to see if it is exactly what you want.
If your question is more "I want to know when a particular page is hit on my remote server": There are plenty of monitoring tools that parse web server logs and event logs to know state of the server. If you want to do something yourself and control the server's code - collect hit information for the page you are interested and provide some page that reports this data.
After few hours of work I have found a solution, not the most elegant one so far,(and at times causes a memory dump) but it does what I need.
Thanks
Just last edit, I solved the crash issue by adding a time so it checks the page every sec or so.
once again thanks for your iterest in my question.
class wait
{
private static System.Timers.Timer aTimer;
public void timed1()
{
// Create a timer with a ten second interval.
aTimer = new System.Timers.Timer(10000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 2 seconds (2000 milliseconds).
aTimer.Interval = 2000;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
//NetKeyLogger klog = new NetKeyLogger();
// Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
Kelloggs.Program KKA = new Kelloggs.Program();
SHDocVw.ShellWindows shellWindows = new SHDocVw.ShellWindows();
string filename;
foreach (SHDocVw.InternetExplorer ie in shellWindows)
{
filename = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
if (filename.Equals("iexplore"))
{
string ddd = (ie.LocationURL);
// Console.WriteLine(ddd);
if (ie.LocationURL == "http://www.testPage.com/")
{
Console.WriteLine("Page found");
// Console.ReadLine();
aTimer.Enabled = false;
KKA.Maino();
}
}

How to programmatically detect when the OS (Windows) is waking up or going to sleep

Background
My son likes to use his laptop when he's not supposed to and I just thought it would be handy if I could write an application that would email me whenever he opened / closed his laptop.
(I'd even settle for something that notified me when there was network traffic on the machine)
Question
How do you programmatically detect when an OS is waking up or going to sleep? I found this link from this related post. But that covers OS X. I'm looking for the same thing for Windows 7.
(I'd like to do this in Java, if possible, but I'd settle for C#/C++)
Easiest way is not to write any code at all, even though this is stack overflow. Click Start, type Schedule and choose Scheduled Tasks. Set one up (click Create Task) and set a Trigger when the machine is unlocked. For the Action, have it send you an email.
Repeat for startup and when a user logs in, if you want. Done.
You're going to want to create a window and watch for the WM_POWERBROADCAST message (http://msdn.microsoft.com/en-us/library/aa373248%28v=vs.85%29.aspx) and check the wParam for your desired action. For example, your window should receive a WM_POWERBROADCAST with PBT_APMSUSPEND as the wParam when the system is about to enter a suspended state (i.e. closing a laptop). Resuming seems to have a few different wParam values: PBT_APMRESUMESUSPEND, PBT_APMRESUMECRITICAL and PBT_APMRESUMEAUTOMATIC
I search for a long time and found that this was the best way, the 'Sleep'-event was never working before:
private ManagementEventWatcher managementEventWatcher;
private readonly Dictionary<string, string> powerValues = new Dictionary<string, string>
{
{"4", "Entering Suspend"},
{"7", "Resume from Suspend"},
{"10", "Power Status Change"},
{"11", "OEM Event"},
{"18", "Resume Automatic"}
};
public void InitPowerEvents()
{
var q = new WqlEventQuery();
var scope = new ManagementScope("root\\CIMV2");
q.EventClassName = "Win32_PowerManagementEvent";
managementEventWatcher = new ManagementEventWatcher(scope, q);
managementEventWatcher.EventArrived += PowerEventArrive;
managementEventWatcher.Start();
}
private void PowerEventArrive(object sender, EventArrivedEventArgs e)
{
foreach (PropertyData pd in e.NewEvent.Properties)
{
if (pd == null || pd.Value == null) continue;
var name = powerValues.ContainsKey(pd.Value.ToString())
? powerValues[pd.Value.ToString()]
: pd.Value.ToString();
Console.WriteLine("PowerEvent:"+name);
}
}
public void Stop()
{
managementEventWatcher.Stop();
}
A very simple, perhaps crude, but effective way may be to have a program with a timer firing every minute. If the timer fires and it's been, say, 5 minutes of real time since its last execution then you can likely assume that the computer was sleeping since it's unlikely that your thread was unable to be scheduled for so long.
The other reason for the difference may be a clock adjustment, like DST or a manual change, but that kind of "noise" should be very low, in your scenario.
You could write a simple app and register it as a Windows service, to be started automatically at system startup. This app could then do whatever you want when it starts. And if it's a proper Windows app, it can register to get notification about impending system shutdown too (I don't remember the details but I implemented this in a C++ MFC app many years ago).
If you prefer Java, you could register your app as a service via a suitable service wrapper like Tanuki (it seems they have a free Community License option). Although this might be overkill. And it may be possible to get notification about the JVM shutting down when the system is closing (but I have no concrete experience with this).
http://www.pinvoke.net/default.aspx/powrprof.CallNtPowerInformation - Check out the link. It has almost all win32api for all windows function. You can call power management feature directly in your windows 7 laptop. For that create a Windows Service , that will use these specific api to notify the machine state.

Categories

Resources