lets say i have 2 Windows ( loginWindow and MainWindow ). When a certain time runs out(lets say 30 seconds) i want that my Program automatically logs of ( open loginWindow ) again. I tried to code a global stopwatch that i can reset from where ever i want to in my Programm so i can open loginWindow after the time runs out.
This is what i got: (also im very new into WPF)
GlobalClass :
public static Stopwatch stopwatch = new Stopwatch();
public static long timeSpan;
public static void startStopwatch()
{
stopwatch.Start();
Thread.Sleep(10000);
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
timeSpan = stopwatch.ElapsedMilliseconds / 1000;
}
public static void restartStopwatch()
{
stopwatch.Stop();
startStopwatch();
}
Page1 (MainWindow):
public Page1()
{
InitializeComponent();
GlobalClass.startStopwatch();
if(GlobalClass.timeSpan == 10)
{
MessageBox.Show("Stopwatch reached end"); //also jump back to loginWindow
}
}
so this doesnt work but i dont know why. my Question is: before i go more into Stopwatch should i solve this Problem with Stopwatch or use a different way to achieve what i want. also why is this not working:(.
thanks in Advance <3
You can implement a timer as a Singelton and register the navigation handler (or your navigation concept) to the TickEvent.
The event is triggered when the time you set has expired and you can return to the logon screen.
You can now start/stop/reset from different locations.
public class GlobalTimer : Timer
{
private GlobalTimer instance;
public GlobalTimer Instance => instance ?? (instance = new GlobalTimer());
private GlobalTimer()
{
}
}
Edit:
A StopWatch, as the name suggests, is a class that measures a time span.
What you want to have is more of an alarm clock that informs you when a certain time has elapsed.
Your program does not work because you are waiting in the UI creation. This means that the UI is not yet drawn and you tell the thread who is drawing
wait 10 seconds and then draw the previous one again. Page1 is therefore not displayed.
Therefore never Thread.wait(x) in a UI thread (your UI freezes when the thread is not working (sleeping)).
Here is a Link to the Timer Class for more information how an Timer work: https://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.110).aspx
Edit 2:
As Clemens said, the DispatcherTimer is the better option for a UI application because events are processed with the UI thread.
If you want to use the "normal" timer, you may have to call UI elements(variables/Methoen/etc.) using a dispatcher.
Otherwise data will be managed in different threads which does not work.
See the answer/more infos here: WPF - Threads and change variable
Related
Part of my program receives input over a network connection, and sends a message back. I want to limit the number of times a certain input can trigger a message, so the program can't be overloaded.
I have a background worker that waits for the input, and then when it receives the certain input, it calls into a static class that will determine if it has been enough time since the last input. I'm using a
System.Windows.Forms.Timer
To do this. It looks like this (everything is public so I can debug):
public static class InputResponse
{
public static System.Windows.Forms.Timer Time = new System.Windows.Forms.Timer();
public static void CreateTimer()//set all the properties of the timer
{
Time.Interval = 3000;
Time.Tick += new EventHandler(Time_Tick);
}
public static void InputAReceived()
{
if (Time.Enabled) //if the timer is running, do nothing
return;
else
{
//send response here
Time.Start();
}
}
public static void Time_Tick(object sender, EventArgs e)
{
Console.WriteLine("Time_Tick");
Time.Stop();
}
}
The problem is, the Time_Tick method never gets called from the timer. I can use Invoke() to trigger the method like so,
EventHandler testHandler = new EventHandler(InputResponse.Time_Tick);
testHandler.Invoke(sender, e);//triggered by a button
which writes to the console like it should, but just waiting for the timer doesn't work. It will send the response once, and then won't send it again, since the timer never gets stopped.
The ridiculous thing is I have it working almost exactly the same in another class. The only difference is that the timer is constantly running.
What am I missing?
One problem with your code is that it is using the System.Windows.Forms.Timer class from a background thread and not associated with a window. This violates the instructions given in the documentation:
This timer is optimized for use in Windows Forms applications and must be used in a window.
For timers not related to GUI objects, use System.Timers.Timer.
This may or may not be the cause of the problems you're having, but it's one thing you'll need to address for your code to work correctly.
In relation to a previous question of mine ([question] : Which thread will timer method run in? ), I've added a Timer to my Windows Forms app to run every 100ms to show how long the program session has been running. I've defined it as follows (these are only the snippets relevant to the timer):
private System.Timers.Timer timerPureTime = new System.Timers.Timer(100);
timerPureTime.Elapsed += new System.Timers.ElapsedEventHandler(updateTimeElapsed);
this.timerPureTime.SynchronizingObject = currentForm; //where currentForm is my main Form
public void updateTimeElapsed(object sender, ElapsedEventArgs e)
{
if (currentForm.lblTimeElapsed.InvokeRequired) //lblTimeElapsed is your standard Windows Form label
{
currentForm.lblTimeElapsed.Invoke((MethodInvoker)delegate //also, trying to make make GUI invoking thread-safe here
{
TimeSpan t = TimeSpan.FromSeconds(purelyTime);
string showTime = string.Format("{0:D2} min {1:D2} sec",
t.Minutes,
t.Seconds);
currentForm.lblTimeElapsed.Text = showTime;
});
}
else
{
TimeSpan t = TimeSpan.FromSeconds(purelyTime);
string showTime = string.Format("{0:D2} min {1:D2} sec",
t.Minutes,
t.Seconds);
currentForm.lblTimeElapsed.Text = showTime;
}
purelyTime += 0.1;
}
As I understand it the Timer should be running in a thread of its own (taken from the Threadpool) however it still experiences some delay every now and then, throwing the timer off-course. Other threads within the application run pretty regularly (every 250ms) and computation-intensive, but shouldn't these be independent of Timer threads?
What could be the possible causes for timer lag in such cases?
Windows cannot guarantee a precisely regular callback for a timer, so you will definitely see that kind of variance.
You need to take a different approach:
Initialise a Stopwatch field in your class.
Call Stopwatch.Restart() when you want to reset the timing.
Inside updateTimeElapsed() use Stopwatch.Elapsed instead of purelyTime.
Note that your code is completely ignoring the amount of time spent in the timer handler function itself. Inside the handler, you are using Invoke to send a message to the UI and waiting for it to return. That can take an arbitrary amount of time, particularly if the UI is busy.
I got a little problem with my application.
I would like to update something on my UI every 10 seconds. I first used a DispatcherTimer for this but it will block my UI for a short time because the update method needs to load something from the web and this operation needs some time.
Now I thought about some kind of background worker and I found BackgroundTasks.
The problem with Background tasks is, as far as I understood it correctly, that they are supposed to serve as updaters even if the app is suspended. I don't need that.
I only would like to update if my app is running not if it is suspended.
Is there a good way to solve this?
Any suggestions what to use for this?
Thanks in advance!
You need two things for it:
Timer
You can update the UI in System.Timers.Timer with the 10 seconds interval.
Dispatcher
You need to use Dispatcher.Invoke to change the UI without holding the main UI thread. Instead the method Process should be called on a separate thread (Timer method), other than main UI thread, and use Dispatcher in it to alert main UI thread for the change.
Process() // method to be called after regular interval in Timer
{
// lengthy process, i.e. data fetching and processing etc.
// here comes the UI update part
Dispatcher.Invoke((Action)delegate() { /* update UI */ });
}
You need to create a thread that runs the part of your code that gets and processes the information from the website. This way, your form will not hesitate because it will be on a different thread than the processing part.
This Article on code-project should get you started.
Also, you could start a timer, which has a elapsed event, that occurs every time the timer passes a certain time cycle.
http://www.dotnetperls.com/timer
The other answers are missing proper cleanup: When the timer fires in the exact moment that the window was closed, I would get an uncaught TaskCanceledException when trying to run Dispatcher.Invoke. I didn't find help for this problem in other questions. I was able to solve it by unregistering the timer callback when closing the window.
public partial class MainWindow : Window
{
Timer clockTimer = null;
public MainWindow()
{
clockTimer = new Timer(1.0); // 1 ms update to test for TaskCanceledException
clockTimer.Elapsed += Timer_Elapsed;
clockTimer.AutoReset = true;
clockTimer.Start();
Closed += (object sender, EventArgs e) => { clockTimer.Elapsed -= Timer_Elapsed; };
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e) {
var now = DateTime.Now;
Dispatcher.Invoke((Action)delegate () {
UpdateTime(now);
});
}
}
Obviously this is not a good idea if the window was re-shown. I tried adding a dtor, but it would never get called, probably due to cyclic dependencies.
Disclaimer: I don't know C#, so this might not be the best or proper way of doing things.
I want to change the index of selected index of listbox after every two seconds.
public Form1()
{
InitializeComponent();
listBox1.Items.Add("A");
listBox1.Items.Add("B");
listBox1.Items.Add("C");
listBox1.Items.Add("D");
listBox1.Items.Add("E");
listBox1.Items.Add("F");
}
public void SelectEvery2Sec()
{
System.Windows.Forms.Timer timer=new System.Windows.Forms.Timer();
for (int i = 0; i < listBox1.Items.Count; i++)
{
timer.Start();
listBox1.SelectedIndex = i;
try
{
Thread.Sleep(2000);
}
catch{}
if(i == listBox1.Items.Count -1)
i = 0;
}
}
But we can not stop main Thread.Then Application run but I could not see GUI. It is not correct way so I am try next way i.e. Another Thread.
Then I will create a new Thread but cross access of thread is not allowed?
Then I will create a new Thread but cross access of thread is not allowed?
Correct. You cannot access UI controls from a non-UI thread. You will get an exception if you try.
Multiple threads are not necessarily the right solution in every case. For this situation, a timer control might be simpler—the one you want is called System.Windows.Forms.Timer.
Alternatively, you could use a BackgroundWorker component. All you have to do is add it to your form at design time and it takes care of all the dirty work for you. There's a great sample on the MSDN page.
Do note that Thread.Sleep is the sign of a poorly-designed program. If you ever find yourself writing that in your code, you're doing it wrong. There's almost certainly a better way.
This type of question gets asked an awful lot on Stack Overflow. You can find more information by performing a search.
You can do this by using Timer or BackgroundWorker. For Timer, set the Interval to 2 secs. For BackgroundWorker use RunWorkerAsync.
For cross thread access issue use
public static class ControlExtensions
{
public static void Invoke(this Control control, Action action)
{
if (control.InvokeRequired) control.Invoke(new MethodInvoker(action), null);
else action.Invoke();
}
}
Your old code
listBox1.SelectedIndex = i;
will become
listBox1.Invoke(() => { listBox1.SelectedIndex = i; });
Instead of a System.Windows.Forms.Timer use a System.Threading.Timer. This can be run in a worker thread.
Have the timer timeout event handler call a function to change the ListBox.SelectedItem, be sure to check Invoke.Required on changing the ListBox selected item as yo umay need to Invoke it.
Set Interval of you timer object to 2000 ms, do not make main thread sleep.
You can hanndle the Timer Elapsed event and update the control.
UPDATE:
For making it by two threads, raise an event in second thread every 2000 ms and wire a method in you Form to it. In that method you can change the controls of your form.
I'm working on a simple web service which exports data from some data store into the database.
The service runs every 20 seconds (testing interval).
Intervals are implemented through System.Timers.Timer class.
What is happening at the moment is:
Service starts
Timer starts
20 seconds pass and service starts the export
Export doesn't finish within next 20 seconds and another thread kicks off attempting to do the same export.
Eventually service crashes.
I was going to wrap the export into a separate thread, but not sure whether this will fully fix the problem.
Increasing a time interval isn't an option because I'm not sure how big the future exports will be.
Any suggestions are welcome.
Thank you
Edit:
I guess what I'm after is:
1. Start timer
2. Start thread
3. Start export
4. Don't let timer to start another thread until previous one completes...
How about in Step 3, you first disable the timer, then when you are done with the export, you re-enable the timer?
I would do something like this.
public class MyServiceController
{
private Thread m_Thread = new Thread(() => { Run(); });
private ManualResetEvent m_StopSignal = new ManualResetEvent();
public void Start()
{
m_Thread.Start();
}
public void Stop()
{
m_StopSignal.Set(); // Give it chance to end on its own.
if (!m_Thread.Join(TimeSpan.FromSeconds(30))
{
// Tear everything down forcefully as an absolute last resort.
m_Thread.Abort();
}
}
private void Run()
{
while (!m_StopSignal(TimeSpan.FromSeconds(20))
{
// Put your code here.
}
}
}
This approach allocates a single dedicated thread for processing which keeps everything synchronous. Notice that it uses a WaitHandle to throttle the intervals. It is also important to note that I have left out a lot of code that would make MyServiceController more robust like dealing with callers who want to call Start multiple times, making sure the worker thread ends if it does not want to stop peacefully, etc.
Sometimes you don't want to stop your timer because it might spawning multiple threads. In this case you wrap the critical parts of each thread in Monitor.TryEnter block, locking on a shared object, so that if a thread is still running when the timer fires again, the new thread falls through harmlessly.
private static object lockObject = new object();
public void DoSomething()
{
if (System.Threading.Monitor.TryEnter(lockObject))
{
try
{
// critical stuff
}
finally
{
System.Threading.Monitor.Exit(lockObject);
}
}
}