I have a TextBox which tells the status of a running application (lets say notepad). If notepad is running Text of TextBox is running and not running for other case.
public string ProcessStatus
{
get
{
IsProcessRunning("Notepad.exe")
return "Running";
return "Not Running";
}
}
Now problem here is that view updates itself only once when it is launched. At that time if notepad is running it works fine. Now lets suppose I ran my application and notepad was not running then TextBox says not running. Now I launch notepad, now application is still saying not running as application has not updated the view. If I call notify of property changed event for the TextBox then it will say running. But I want here is that TextBox updates automatically.
The only solution what I am thinking right now is that I start a background process which keeps on updating ProcessStatus. But is this the right way? Is there any better way? Something like DirectoryWatcher for processes?
You could use a System.Windows.Threading.DispatcherTimer to check at regular intervals:
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(10000); // checks every 10 seconds
timer.Tick += Timer_Tick;
timer.Start();
...
private void Timer_Tick(object sender, EventArgs e)
{
// do your checks here
textbox.Text = ProcessStatus;
}
You can find out more about the DispatcherTimer class from the DispatcherTimer Class page at MSDN.
Why not use the timer class to periodically run ProcessStatus, you can define the interval.
On this other question Can I Get Notified When Some Process Starts? there are two answers on how you can get notified if a process (e.g. Notepad.exe) starts. Both are neither ideal nor simple, I would probably stick to polling as Sheridan and NSmeef suggested.
Related
A form should open only when there is an event if there is no event it should not display on the screen. So Basically i thought of using a timer to do this. An exe will continously be running and after every minute it checks the db to see if there is data and if there is it shows up on the screen and will only be closed manually with user interaction. After a minute it checks again and displays the form if Data is present in the DB.
I used system.threading.Timer in Program.cs file to open a window after every minute.Below is the code
timer = new System.Threading.Timer((s) => {
EL.CustomMessageBox l = new EL.CustomMessageBox();
l.ShowDialog();
}, null, TimeSpan.Zero, 60000);
After certain time I see that this exe is still running in the taskmanager but even though there is data in the DB it stops showing up on the screen. Any help is appreciated.
System.Threading.Timer runs its callback on a threadpool thread. You should never use a threadpool thread for UI work, because:
They don't run a message dispatch loop.
You don't control when the thread gets recycled. UI windows have thread affinity and if their thread exits all the associated windows go poof immediately (you won't even get WM_DESTROY messages).
A normal Application.Run loop on the main thread, with a hidden main window and a UI timer will serve you much better.
I would pass my own custom ApplicationContext to Application.Run() in program.cs.
This will allow you to have NO INTERFACE until your conditions are met. The application will also continue to run (even when you close the Forms) until you explicitly call Application.Exit().
You can keep a reference to your Form at class level. This will help you decide if you need to work with the existing one, or create a new one.
Note that I'm using the System.Windows.Forms.Timer, not the threaded timer.
Something like...
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MyContext());
}
}
public class MyContext : ApplicationContext
{
private EL.CustomMessageBox l = null;
private System.Windows.Forms.Timer timer;
public MyContext()
{
timer = new System.Windows.Forms.Timer();
timer.Interval = (int)TimeSpan.FromMinutes(1).TotalMilliseconds;
timer.Tick += Timer_Tick;
timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
bool result = true; // hit the database and get an answer
if (result)
{
if (l == null || l.IsDisposed)
{
// no form has been created yet, or the previous one was closed
// create a new instance
l = new EL.CustomMessageBox();
l.Show();
}
else
{
// if we get in here, then the previous form is still being displayed
// if your form can be minimized, you might need to restore it
// if (l.WindowState == FormWindowState.Minimized)
// {
// restore the window in here?
// }
}
// update the form "l" with some data?
l.xxx = yyy;
}
}
}
I can't help but think that the other answers, massively technically correct as they are, don't actually solve the problem because they probably don't make sense if you aren't aware of how Windows works. Idle_Mind's is closest to what I'd do, though if the forms designer is familiar I'd go for a solution that basically just uses that - as such I present what I would do to solve the task you're faced with:
Have an app with one form (or make this form an autonomous one within another app, but for now maybe do it as a dedicated app for simplicity) - make a new Windows Forms project
Have a Timer (a Windows Forms timer, out of the toolbox, not a System.Threading timer) with an interval of 60000 and Enabled = true
Have a timer Tick event handler on your form (double click the timer in the tray under the form designer to attach an event handler) that queries the DB and finds if there are any messages
If there are new messages, adds them to a listbox or something, and calls this.Show() to show the form
Have an eventhandler attached to the FormClosing event so when the user clicks X, the form hides instead of closes:
private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
Hide();
}
}
Maybe have the FormClosing event clear the messages listbox. This way if the form opens and the user is on lunch, the messages will build up and build up, then they can read them and clear them by closing the form. Calling Show on an already-visible form does nothing, so the messages will just accumulate into the listbox if more messages come in and the form is already visible
Good quick rule of thumb; never use System.Threading Timer in a Windows Forms app. Use a timer out of the forms designer toolbox instead. Only use a threading timer if you're writing a service or Console app etc. For stability reasons, Windows controls absolutely must be accessed by the thread that originally created the control. Windows forms timer is aware of this and its Tick event can safely access the controls (a form is a control, showing it requires to access it) in a Forms app
You should call Invoke to execute your delegate on the thread that owns the control's underlying window handle.
Something like this should work:
timer = new System.Threading.Timer((s) => {
EL.CustomMessageBox l = new EL.CustomMessageBox();
l.Invoke((Action) () =>
{
l.ShowDialog();
});
}, null, TimeSpan.Zero, 60000);
Or even better, use this extension method:
public static void InvokeIfRequired(this Control c, MethodInvoker action)
{
if (c.InvokeRequired)
{
c.Invoke(action);
}
else
{
action();
}
}
And call it like this:
l.InvokeIfRequired(() => { l.ShowDialog(); });
Further information can be found at: https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls?view=netframeworkdesktop-4.8
I have a timer in my application in Windows Phone 7.1 implemented using
DispatcherTimer _timer;
Initialized as
Sample._timer = new DispatcherTimer();
Sample._timer.Interval = new TimeSpan(0, 0, 1);
Sample._timer.Tick += new EventHandler(Timer_Tick);
Sample._timer.Start();
private void Timer_Tick(object sender, EventArgs e)
{
double newValue = Sample.Value + 1.686;
if (newValue >= 100)
newValue = 0;
Sample.Value = newValue;
txtDigitalClock.Text = GetTime();
}
public string GetTime()
{
time += TimeSpan.FromSeconds(1);
return string.Format("{0:D2}:{1:D2}:{2:D2}", time.Hours, time.Minutes, time.Seconds);
}
This is working fine in normal condition
Here is my problem
1) Timer is not running when phone is in locked state(screen is loced)
2) Timer is not running when application is running in background (When you press start button in windows phone the app goes to background).
any help would be greatly appreciated..
To run your App (and Timer) under lock screen, you have to disable ApplicationIdleDetectionMode.
If you don't disable idle your App will stop as it is said at MSDN:
This event (Deactivation) is also raised if the device’s lock screen is engaged, unless application idle detection is disabled.
If you want to run Timer in the background (eg. after pressing Start buton), you won't be able to do this as MSDN says:
When the user navigates forward, away from an app, after the Deactivated event is raised, the operating system will attempt to put the app into a dormant state. In this state, all of the application’s threads are stopped and no processing takes place, but the application remains intact in memory.
The bigger problem is when your App is tombstoned - the app doesn't ramain (all) in memory.
You can try to do your job with Background Agents, but that is other story.
Also remember about Certification requirements when your App disables Idle or uses Background Agent.
Similar problem was here.
I searched for your question on google (cuz I'm not into Winphone) and found
http://stackoverflow.com/questions/8352515/how-can-i-run-my-windows-phone-application-in-background
apparently it simply is not possible.
I hope this answers your question
Please write below line timer Initialization
ApplicationIdleModeHelper.Current.HasUserAgreedToRunUnderLock = true;
I resolved this issue by saving the starting timer of the value on isolated storage
IsolatedStorageSettings.ApplicationSettings.Add("TimerStarted",DateTime.UtcNow);
And when the app is reactivated after going to background, i will look for this value in isolated storage and use that to show the timer
I'm trying to raise an event at a given time in my windows store app. Now I've done this in desktop apps countless times, and I've used System.Threading.Timer in the past and it has worked well, but that class is not available to windows store apps.
I have looked in the documentation and found a class called DispatchTimer and although it appears to be what I'm after, correct me if I'm wrong but the docs are lacking. But luckily it's pretty easy to use.
So I tried the DispatchTimer, but after using it, I'm not even sure this is what I should be using.
How can I watch for any given time and raise an event when that time is up (in a windows store app)? And do you know of any resources that do this in a metro app?
Use DispatcherTimer like this:
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(10) };
timer.Tick += OnTimerTick;
timer.Start();
private void OnTimerTick(object sender, object args)
{
// Do something with pickup here...
}
This will create a timer with intervals of 10 seconds.
The DispatcherTimer is the way to go. Notice that if you want your app to run in background you must declare that on the app manifest or use Background agents.
Hopefully this isn't too difficult to follow.
I'm currently working on a small timelogging application that runs quietly in the background. Every time the ticker runs down, the application prompts the user to say what he/she was doing since the last prompt. I'll eventually have the application write the data into a spreadsheet.
One of the options I have so far enables the user to choose whether or not he/she would like to use the default prompting setting (every time a prompt is missed, it stays visible until the next one is created, meaning if the user leaves his/her computer for a while there may be a fair few prompts sitting on the screen waiting to be filled in) or would like to combine all the prompts (every time a prompt is missed and a new one pops up, the old one is closed and the new one covers the time of the old prompt and the new prompt).
The user can also select a tickbox to turn prompts off. When he/she turns prompts back on again, a prompt pops up asking the user to fill in what he/she was doing while prompts were turned off (useful when the user is running fullscreen applications, etc).
My problem is, when I try to generate the prompts, they don't display correctly. I can't manipulate them at all and none of the controls display. They basically look like empty forms.
Here's my code for generating prompts using the ticker:
public void ticker(object source, System.Timers.ElapsedEventArgs e)
{
if (groupMissed)
{
incrementsMissed += 1;
if (incrementsMissed > 1)
{
IncrementForm form = (IncrementForm)Application.OpenForms["IncrementForm"];
if (form.InvokeRequired)
{
form.Invoke(new MethodInvoker(delegate { form.Close(); }));
}
}
}
else
{
incrementsMissed = 1;
}
IncrementForm theIncrementForm = new IncrementForm(this, e.SignalTime);
theIncrementForm.Show();
latestIncrement = e.SignalTime;
}
And here's my code for generating prompts using the "turn prompts off" checkbox:
private void chkbxAlerts_Click(object sender, EventArgs e)
{
if (!chkbxAlerts.Checked)
{
// Ensures that the time missed is covered and restarts the timer
DateTime now;
now = DateTime.Now;
if ((now - latestIncrement).TotalMinutes >= 1) // Only records time if it is equal to or greater than one minute
{
// TO-DO: FIX
if (groupMissed)
{
incrementsMissed += 1;
if (incrementsMissed > 1)
{
IncrementForm form = (IncrementForm)Application.OpenForms["IncrementForm"];
if (form.InvokeRequired)
{
form.Invoke(new MethodInvoker(delegate { form.Close(); }));
}
}
}
else
{
incrementsMissed = 1;
}
IncrementForm theIncrementForm = new IncrementForm(this, now, latestIncrement);
theIncrementForm.Show();
latestIncrement = now;
}
timer.Enabled = true;
}
else
{
// Stops the timer
timer.Enabled = false;
}
}
If you need any further clarification, please let me know. Thanks so much in advance for any help, this has been bugging me.
System.Timers.Timer has a SynchronizingObject property. If you set that to the main form (or the form that contains the timer), then the timer tick event will be raised on the GUI thread.
Do note that System.Timers.Timer has the nasty habit of swallowing exceptions that occur in the Elapsed event. If your tick handler throws an exception, you'll never see it. It's a nasty bug hider. For that reason, I recommend using either System.Windows.Forms.Timer or System.Threading.Timer. If you use the Windows Forms timer, the elapsed event is raised on the GUI thread. If you use System.Threading.Timer, you'll have to use Invoke as NSGaga shows in his answer.
See Swallowing exceptions is hiding bugs for more information about why I discourage the use of System.Timers.Timer.
I think, from what I can see, not 100% but your timer is spawning your windows in a separate thread (being from the timer ticker call).
While theoretically that can work (take a look at this How to open a form in a thread and force it to stay open)
...you may be much better off staying within the main thread.
Try something like this...
yourMainWindow.Invoke(new MethodInvoker(() =>
{
IncrementForm theIncrementForm = new IncrementForm(this, e.SignalTime);
theIncrementForm.Show();
latestIncrement = e.SignalTime;
}));
...that's from your timer - that way (as I can see) you should have it all 'on the main thread' and make things much easier for you.
hope this helps
I am using VS2010 - WPF - C#
in my application I fetch data from a web server and view it on my interface
the problem is that I want to keep fetching data and keep refreshing my interface every 3 minutes but I don't know how to do that...
I tried (Thread.Sleep(18000)) and it didn't work because my interface wouldn't show at all
I don't know how to use the Timer for such reason and I couldn't find what I'm looking for elsewhere
Please can you help me with it ?
Best Regards
What programming model? Stock or something more sane with a MVVM approach?
Anyhow, use a TIMER to request a callback after 3 minutes. In the callback invoke back to the dispatcher thread of the window once you got the results of the web service call. Finished.
Use a DispatcherTimer, there are also examples how to use it on the given link
Use a dispatch timer like this
Delcare it
public System.Windows.Threading.DispatcherTimer timer1;
In the constructor
timer1 = new System.Windows.Threading.DispatcherTimer();
timer1.Interval = TimeSpan.FromSeconds(180); // 3 mintues interval
timer1.Tick += TimerTicked; // Event for handling the fetching data
Do your job
private void TimerTicked(object sender, EventArgs args)
{
//Fetch the data
}
timer1.start(); // Whereever you want to start the timer