Issue with timer updating Form - c#

I have a recursive function and would like to update the form with the time, number of attempts and what the current attempt for the recursive function. Every second, the form should update. The current methodinvoker doesn't work. The compiler will highlight the line but not continue and it will pop back out.
I already tried placing the function on a separate thread but, it preforms poorly, so I would prefer to keep the function on the main thread.
Any ideas?
void bruteForce_DoWork()
{
doBruteForceEID("", 0, wordlen, temp);
}
void _myTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (InvokeRequired)
{
runTimeSec++;
this.Invoke(new MethodInvoker(delegate() { this.toolStrip.Text = "Running... " + runTimeSec + "s"; }));
Invoke(new MethodInvoker(delegate() { lblAttackA.Text = Convert.ToString(attackCount); }));
Invoke(new MethodInvoker(delegate { lblCurAttempt.Text = brute; }));
}
else
{
runTimeSec++;
toolStrip.Text = "Running... " + runTimeSec + "s";
lblAttackA.Text = Convert.ToString(attackCount);
lblCurAttempt.Text = brute;
}
}
EDIT: Let me explain the program alitte more... Once the user has inputted their password that they would like to check, the following happens after they hit Calculate.
- Runs a dummy recursive algorithm to see how many cycles their machine can do within 5 seconds, then I average them to give a better idea of how many cycles they can do per sec.
back = new Thread(new ThreadStart(testLoop_DoWork)); // Calls the dummy algorithm
back.Start();
if (rbtnTest.Checked)
{
txtEID.Text = txtUID.Text;
lblRunCycle.Text = "Calculating...";
testTimer.Enabled = true; // Starts the Timer
}
Once the 5 second timer is up, I check the length, cycles per second, what characters (upper,lower,numbers,symbols), give how long it will take, add the respective char arrays for to create the brute force char array, then I Join() the thread and disable the timer.
I would get roughy 7million cycles per second avg...(remember this number). Also, I am NOT updating to the GUI during this time.. Just running the created thread.
Then if the user wants to run the attack, it does:
attackBack = new Thread(new ThreadStart(bruteForce_DoWork));
attackBack.Start();
_myTimer.Enabled = true;
Once I start running it on the new thread, it is displaying only about 30,000 cycles per second?? and my timer is only updating every second. What is going on?
Edit: I also just commented out the timer so nothing is updating to the GUI... and the same results occur when the brute force is found (for example the word 'test' should be instant... but it takes 10 seconds to find it...

Yes, this cannot work. The Timer.Elapsed event runs on a threadpool thread. Which means for one that InvokeRequired is always true and doesn't need to be checked. What can't work is the Invoke() call. It requires the UI thread to be idle so it can executed the invoked code.
Your UI thread isn't idle, it is executing the expensive code. This is called deadlock.
You have to do this the other way around, have a worker thread execute the expensive code instead of the UI thread. Which keeps the UI thread responsive, both to update the labels, keep the UI painted and respond to user input. You said you didn't like doing it this way, it is unclear why you are having a problem with it. A classic mistake is updating the UI too often, flooding it with invoke requests so it doesn't get around to its regular duties anymore. A timed update is indeed the solution. Never update more than 25 times per second, the human eye can't tell the difference if you do it more often than that.

Related

C# background worker frozen the GUI

I'm trying to use background worker to update a text label continuously, but for DoWork, if no loop used, it will only execute once, but if infinite loop is used, it freezes the GUI, any idea to solve this? Really appreciate!!! I'm pretty new to C# and still trying to learn.
Here's my code:
This in the main form:
backgroundWorkerX.DoWork += backgroundWorkerX_DoWork;
backgroundWorkerX.ProgressChanged += backgroundWorkerX_ProgressChanged;
backgroundWorkerX.WorkerReportsProgress = true;
backgroundWorkerX.RunWorkerAsync();
Then:
public void backgroundWorkerX_DoWork(object sender, DoWorkEventArgs e)
{
X = -(RSSI_PI1_ST1);
backgroundWorkerX.ReportProgress(X);
}
public void backgroundWorkerX_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label9.Text = e.ProgressPercentage.ToString();
}
public void backgroundWorkerX_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
[...] if no loop used, it will only execute once
This is the expected behavior. It will do the thing it's expected and then call RunWorkerCompleted.
[...] but if infinite loop is used, it freezes the GUI.
You don't present a loop in your question. So I'll make an assumption and will give you an educated guess that it actually consumes all the CPU, and therefore crashes the GUI.
// I assume that you loop like this somehow.
do
{
X = -(RSSI_PI1_ST1);
backgroundWorkerX.ReportProgress(X);
} while (true);
Try to add something to "slow it down" once in a while. Otherwise it will just run and run as fast as possible, and therefore consume all the CPU available. Remember that everytime you use ReportProgress it will be rendered by the GUI-thread. And this will execute very often and not leave a lot of resources for the GUI thread to respond to other things. Below I use Thread.Sleep, which will pause the thread for half a second. But remember that you will only want to do this in a background thread.
do
{
X = -(RSSI_PI1_ST1);
backgroundWorkerX.ReportProgress(X);
Thread.Sleep(500);
} while (true);
I would also consider doing this another way. If you actually have the need of pausing the thread, you might as well do it with a Timer. Thread.Sleep will lock the thread, and may therefore not be what you really want. From this answer:
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 */ });
}

UI button running on separate thread?

my issue is the following:
1.I have an intensive method which updates GUI element (chart) in a while loop
2.I need to break out of this loop when a button is pressed.
3.Problem is the button event handler doesn't get executed until the while loop is finished.
4.I've tried running the method on separate thread but that is very problematic since it sets and reads many UI elements, pretty much I couldn't get that to work, so I'm hoping of there being a way to run just the stop button on a separate thread and update a global variable which let's me break out of the loop.
Any Idea how that can be accomplished?
private void playBack(int playTime, int runUntil)
{
var frameTime = new DateTime(); var frameTime_ = new DateTime();
bool fwd = true;
if (runUntil < playTime) fwd = false;
playTime = trPlay.Value;
playGoStop = true;
lbPlayTime.Text = (playTime * numDtStepSize.Value).ToString();
while (true) //trPlay.Maximum + 1)
{
frameTime = DateTime.UtcNow;
if ((frameTime - frameTime_).TotalMilliseconds > (double)(1000 / numFps.Value))
{
systemUpdate(playTime);
trPlay.Value = playTime;
trPlay.Update();
lbPlayTime.Update();
frameTime_ = frameTime;
if (fwd)
{
playTime++;
if (playTime > runUntil) break;
}
else
{
playTime--;
if (playTime < runUntil) break;
}
}
if (!playGoStop) break;
}
}
In your while loop, you can call Application.DoEvents(). It will fetch UI events from event queue, and process those events. Then, your button events will be processed.
You can search by the keyword Application.DoEvents() and C#. There are many topics about it.
UPDATE:
In your codes, it is a infinite while loop inside. I don't like to run a infinite in main thread. I will prefer to run it in a worker-thread. And send message to do UI updates in main-thread. Generally, UI events needs to be processed in the main-thread.
If the infinite while loop is already in the worker-thread, it should sleep about 5~10 ms per loop, in order to free CPU resources to process some events in the other threads.
You should look at binding your UI element (chart) data to a DependencyProperty. This allows you to run the intensive method on a non-UI thread, allowing your UI thread to be responsive to button clicks. While on the background thread, simply make Dispatcher.BeginInvoke() calls to update your DependencyProperty (as it can only be updated from the UI thread) and this will update your control bound to it.
As far as your button interrupt goes, a simple solution is to set a flag from your UI which is checked within each loop iteration. A more complex solution would be to run this intensive method in a task Task, giving it CancellationTokenSource, then cancel the source upon button click.

Background timer to update UI?

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.

"Simple" C# Time Thread Appears to be Freezing

I've been staring at this thread for some time and I believe my mind has shut down on it. Thinking that the best thing to do, in order to update the time in a UI TextBox, would be to create what I thought would be a simple thread to get the time and post it back to the UI control. After having fought with it for a while, I'm getting frustrated and thinking that I might just add the time in some other way. In the intrepid spirit of the adventurer, I'm giving it another go.
I've got a similar thread operating elsewhere in the app that takes a list and populates a DataGridView in a TabControl. I'd have thought that the process would be roughly the same, but I'm missing a key part. The entirety of the thread is below:
private void displayTime()
{
while (true)
{
String time;
String date;
time = DateTime.Now.TimeOfDay.ToString();
int len = time.IndexOf('.');
time = time.Substring(0, len);
date = DateTime.Now.Date.ToString();
len = date.IndexOf(' ');
date = date.Substring(0, len);
updateClock(time, date);
}
}
private void updateClock(String time, String date)
{
if (InvokeRequired)
{
BeginInvoke(new timeDel(updateClock), new object[] {time, date});
return;
}
ctrlTimeTxt.Text = time + "\n" + date;
}
The above thread has been started in various places(in an attempt to debug), but is currently in the Form's Shown event handler. The Form begins to appear, but then everything seems to hang. When I place a breakpoint in the thread, I can step ad infinitum, but the UI never seems to get control back. What am I missing? I'll be happy to expand upon any neglected details.
Edit: A clarification: This thread is being started in a function that is handling the Shown event. The description of the Shown event is given as: Occurs whenever the Form is first shown. I think that might eliminate the theory that the UI thread is Invoking too quickly.
The problem is that your while loop here is generating so many events that the event queue gets flooded:
while (true)
{
// ...
updateClock(time, date);
}
Instead of doing this in a thread you can use a Timer to generate events at a regular interval and do one step of your method for each event. This will also mean that you don't have to use Invoke as the timer generates events on the main thread.
There are also two other errors in your code:
Occasionally TimeOfDay.ToString() could output a time that hits exactly at a second change, in which case the result of ToString() will not be "12:23:34.00000" but just "12:23:34" which will cause your method to throw an exception.
You are calling DateTime.Now twice, but the value could have changed in between the two calls. Normally this won't matter but as it passes midnight it could show '23:59:99.999' but the day shows as the next day. It's probably not a significant error in this application but you ought to get into the habit of only calling DateTime.Now once when you want consistent values for the date and time.
To fix these errors and to simplify your code:
Add a timer to your form.
Set the timer's Enabled property to true in the designer.
Add this event handler to the Tick event:
private void timer_Tick(object sender, EventArgs e)
{
DateTime now = DateTime.Now;
textBox1.Text = now.ToString("HH:mm:ss\nyyyy-MM-dd");
}
You may wish to adjust the format string depending on your needs.
It doesn't surprise me that this isn't going well -- you're stuffing invokes in the UI thread message queue (with your BeginInvoke()) as fast as you can generate them. You may want to put a break (i.e. with System.Threading.Thread.Sleep()) in your displayTime() thread to give the UI thread time to do some work.
How do you call displayTime?
If your Form.Show() method is like this
Show()
{
displayTime();
}
Then as Mark answered you are blocking your main UI thread infinitely.
I would start a new thread
Show()
{
Action displayTimeAction = displayTime;
displayTimeAction.BegingInvoke(null, null);
}

Pausing a method for set # of milliseconds

I need to do a sort of "timeout" or pause in my method for 10 seconds (10000 milliseconds), but I'm not sure if the following would work as i do not have multi-threading.
Thread.Sleep(10000);
I will try to use that current code, but I would appreciate if someone could explain the best and correct way of doing this, especially if the above code does not work properly. Thanks!
UPDATE: This program is actually a console application that in the function in question is doing many HTTPWebRequests to one server, so I wish to delay them for a specified amount of milliseconds. Thus, no callback is required - all that is needed is an "unconditional pause" - basically just the whole thing stops for 10 seconds and then keeps going. I'm pleased that C# still considers this as a thread, so Thread.Sleep(...) would work. Thanks everybody!
You may not have multi-threading, but you're still executing within a thread: all code executes in a thread.
Calling Thread.Sleep will indeed pause the current thread. Do you really want it to unconditionally pause for 10 seconds, or do you want to be able to be "woken up" by something else happening? If you're only actually using one thread, calling Sleep may well be the best way forward, but it will depend on the situation.
In particular, if you're writing a GUI app you don't want to use Thread.Sleep from the UI thread, as otherwise your whole app will become unresponsive for 10 seconds.
If you could give more information about your application, that would help us to advise you better.
Thread.Sleep is fine, and AFAIK the proper way. Even if you are not Multithreaded: There is always at least one Thread, and if you send that to sleep, it sleeps.
Another (bad) way is a spinlock, something like:
// Do never ever use this
private void DoNothing(){ }
private void KillCPU()
{
DateTime target = DateTime.Now.AddSeconds(10);
while(DateTime.Now < target) DoNothing();
DoStuffAfterWaiting10Seconds();
}
This is sadly still being used by people and while it will halt your program for 10 seconds, it will run at 100% CPU Utilization (Well, on Multi-Core systems it's one core).
That will indeed pause the executing thread/method for 10 seconds. Are you seeing a specific problem?
Note that you shouldn't Sleep the UI thread - it would be better to do a callback instead.
Note also that there are other ways of blocking a thread that allow simpler access to get it going again (if you find it is OK after 2s); such as Monitor.Wait(obj, 10000) (allowing another thread to Pulse if needed to wake it up):
static void Main() {
object lockObj = new object();
lock (lockObj) {
new Thread(GetInput).Start(lockObj);
Monitor.Wait(lockObj, 10000);
}
Console.WriteLine("Main exiting");
}
static void GetInput(object state) {
Console.WriteLine("press return...");
string s = Console.ReadLine();
lock (state) {
Monitor.Pulse(state);
}
Console.WriteLine("GetInput exiting");
}
You can do this with Thread.Interrupt too, but IMO that is messier.
You could use a separate thread to do it:
ThreadPool.QueueUserWorkItem(
delegate(object state)
{
Thread.Sleep(1000);
Console.WriteLine("done");
});
But, if this is a Windows Forms app, you will need to invoke the code after the delay from the Gui thread (this article, for example: How to update the GUI from another thread in C#?).
[Edit] Just saw your update. If it's a console app, then this will work. But if you haven't used multiple threads so far, then you need to be aware that this code will be executed in a different thread, which means you will have to take care about thread synchronization issues.
If you don't need background workers, stick to "keeping it simple".
Here is a pause class that will pause for the desired milliseconds and wont consume your CPU resources.
public class PauseClass
{
//(C) Michael Roberg
//Please feel free to distribute this class but include my credentials.
System.Timers.Timer pauseTimer = null;
public void BreakPause()
{
if (pauseTimer != null)
{
pauseTimer.Stop();
pauseTimer.Enabled = false;
}
}
public bool Pause(int miliseconds)
{
ThreadPriority CurrentPriority = Thread.CurrentThread.Priority;
if (miliseconds > 0)
{
Thread.CurrentThread.Priority = ThreadPriority.Lowest;
pauseTimer = new System.Timers.Timer();
pauseTimer.Elapsed += new ElapsedEventHandler(pauseTimer_Elapsed);
pauseTimer.Interval = miliseconds;
pauseTimer.Enabled = true;
while (pauseTimer.Enabled)
{
Thread.Sleep(10);
Application.DoEvents();
//pausThread.Sleep(1);
}
pauseTimer.Elapsed -= new ElapsedEventHandler(pauseTimer_Elapsed);
}
Thread.CurrentThread.Priority = CurrentPriority;
return true;
}
private void pauseTimer_Elapsed(object sender, ElapsedEventArgs e)
{
pauseTimer.Enabled = false;
}
}
Yes, that works just fine.
You don't have to have multiple threads to make use of some of the methods in the Thread class. You always have at least one thread.
For a timeout, you should have a static volatile boolean isRunning class field. When the new thread starts, the isRunning must become true, and at the end must become false.
The main thread should have a method that loops for the isRunning during the timeout you define. When the timeout ends, you should implement the logic. But, never use the abort thread method.
A pause... there isn't a straightforward solution. It depends on what you are doing inside the thread. However, you could look at Monitor.Wait.
If you can have an async method, you can do something like to pause the function at a certain location. Once pause is set false it will continue executing the rest of the code in the method. Since this is an async method and delay is async too UI execution wouldn't be affected.
* Please note that asyn is supported only in .net 4.5 and higher.
bool pause = true;
void async foo()
{
//some code
while (pause)
{
await Task.Delay(100);
}
//some code
}

Categories

Resources