How to stop a timer/change system UI OnSleep Xamarin Android - c#

So I have an app that on a button press: starts a timer, cycles through one (++) piece of data and hides the start button and instead shows a stop and next button.
I have looked into messaging center and I thought it was fixing the problem (here's the link Xamarin.Forms how do I access a public function from another CS file?) but it didn't fix the problem completely.
If the app has the timer running (aka you hit the start button) and then interrupt the process by hitting the home button on your phone, the app works fine and the app hides the stop/next buttons and shows the start button and stops the timer. If you haven't started the process at all (aka you haven't hit the start button) and you hit the home button on your phone the app throws an exception error because what I'm changing with messaging center "doesn't need changing because it never changed". Is there a better way to handle this situation?
Can I use if/else statements in app state with messagingcenter?? I'm stuck.
App.xaml.cs
protected override void OnSleep()
{
// Handle when your app sleeps
Debug.WriteLine("~~~~~~~~~~~~~~OnSleep~~~~~~~~~~~~~");
MessagingCenter.Send<App>(this, "OnSleep");
}
MainPage.xaml.cs
MessagingCenter.Subscribe<App>(this, "OnSleep", (sender) => {
//shows start button instead of stop button
StartGrid.IsVisible = true;
//hides stop button
StopNextGrid.IsVisible = false;
//stops timer
timer.Stop();
timer = null;
//stops sound
startSound.Stop();
stopSound.Play();
});

Just can see the partial code,you should check if your timer is initialized before executing the method.
When you do not click the start button, you need to check whether the timer is initialized, in order to perform the following timer operation.
If no want to know whether timer is initialized. You can try this:
Modify in your notification handling method.If the state of your timer and button has not changed, you don't need to do anything in the notification.Here I use the timer as a judgment.
MessagingCenter.Subscribe<App>(this, "OnSleep", (sender) => {
//shows start button instead of stop button
if (null != timer)
{
StartGrid.IsVisible = true;
//hides stop button
StopNextGrid.IsVisible = false;
//stops timer
timer.Stop();
timer = null;
//stops sound
startSound.Stop();
stopSound.Play();
}
});

Related

How to fix while loop crashing program

I'm trying to have serial data sent out continuously while a check button is being pressed in Visual Studio. So far, this is what I've come up with:
private void checkBox1_CheckedChanged_1(object sender, EventArgs e)
{
while (checkBox1.Checked)
{
serialPort1.Write("D");
Task.Delay(100);
if (checkBox1.Checked != true)
{
break;
}
} `
For some reason, whenever I launch the program and check the box, the program
freezes. I can't exit the program or minimize it or anything. It just stops in its tracks.
The user interface in Windows is based on messages. Your while loop runs in the thread where those messages would be handled. While your code runs, no messages are handled. The user interface cannot be redrawn and cannot react to user input.
Better approach: Use a Timer component. The Tick event of the Timer will be executed every n milliseconds according to the Interval property of the Timer. In the Tick event, you can check the Checkbox state and then do something or not depending on whether the checkbox is checked.
This is a good approach if "do something" is a very short activity. For longer activities, you nee a bit more complex setup that is beyond the scope of a SO question unless you provide more details.
You're blocking the UI thread because your event is being handled synchronously. Refer to this answer for some tips on async/await programming: How do I update the GUI from another thread?

continue of timer after closing the form

var startTime = DateTime.Now;
var timer = new Timer() { Interval = 1000 };
timer.Tick += (obj, args) =>
label14.Text =
(TimeSpan.FromMinutes(Convert.ToDouble( comboBox3.Text)*60) - (DateTime.Now - startTime))
.ToString("hh\\:mm\\:ss");
MessageBox.Show("Timer started");
timer.Enabled = true;
im strating a timer in a specific form when pressing a button, i want the timer to continue counting time after closing the form in order to give me a notification.
but when closing the form the timer stops,
any ideas?
You can't "Close" the form and have the Timer object still work (if you're calling the timer on the main form). (That's like saying I can't click the button and have a function run after closing the form). However, on the OnFormClosing argument, you could have the form.Visible = false and cancel the actual closing of the form. See here: Timer doesn't fire after Form closed
If you want to truly close the form and have it run, one option could be to look at possibly creating a Task Scheduler object that would complete the task at a certain time.
A quick hit: call "Hide()" instead - that will keep the timer running.
Now that's out the way, You can still make your timer static - ideally put it in a completely separate class, or, if you insist, make it static on your main form. Then have your notification code sit on your main form.
You can still add a listener to the Tick event on that specific form and just remember to remove it when you hide the form (i.e. Tick -= your_label_event_handler)

How do I prevent any button click events from queuing until the event handle is finished with the first call

I want to prevent a button click from queuing. In testing I have a Form, a Button and in the Code-Behind I have the event handler:
private void button1_Click(object sender, EventArgs e)
{
if (_codeRunning)
return;
_codeRunning = true;
//Application.DoEvents();
//button1.Enabled = false;
_click ++;
Debug.WriteLine("Click Number: " + _click);
Task.Delay(5000).Wait();
//button1.Enabled = true;
_codeRunning = false;
}
When I run debug and click the button twice or three or four times rapidly, Debug Output shows each click about five seconds after the last one. What I would like it to show is a single Click and drop the rest until first Event is complete.
I have also tried to disable the button, as well as temporarily remove the Handler from the Button_click event. It is all the same results.
There are various amounts of trouble you'll get into when you hang-up the UI thread like this. This is certainly one of them, nothing pleasant happens when the user wildly bangs on the button to try to get something noticeable to happen. And sure, those clicks won't get lost, they stay stored in the message queue. To activate your Click event handler again when your event handler stops running.
Pretty important to learn how to use the BackgroundWorker or Task classes to avoid this kind of trouble. Just setting the button's Enabled property is then enough to solve this problem.
Purging the mouse clicks from the message queue is technically possible. But ugly to do, it requires pinvoke. I'll hesitantly post the alternative, don't assume that this is in general a good strategy. You'll need to read this post to have some insight into why DoEvents() is a dangerous method.
private void button1_Click(object sender, EventArgs e) {
button1.Enabled = false;
button1.Update();
'' long running code
''...
Application.DoEvents();
if (!button1.IsDisposed) button1.Enabled = true;
}
The Update() call ensures that the user gets the feedback he needs to know that banging the button repeatedly isn't going to do anything useful. The DoEvents() call will dispatch all the queued-up mouse clicks, nothing happens with them since the button is still disabled. The IsDisposed test is essential to solve the problem with DoEvents(), it ensures your program won't crash when the user clicked the window's Close button while the code was running.
Use the HourGlass class in this post to provide more feedback.
I had a button that on click event was going to run a method. Same issue happent and when the user clicked multiple times the method was triggered multiple times. So I made a boolean and changed it value when the method started.
private bool IsTaskRunning = false;
private void MyMethod()
{
if ( IsTaskRunning==false )
{
IsTaskRunning=true;
// My heavy duty code that takes a long time
IsTaskRunning=false; // When method is finished
}
}
So now the method runs only if it's done the last time.

How to terminate windows phone 8.1 app

I want to exit my app when the user press back button. I have used Hardware Pressed events to navigate between pages.
When I navigated to the first page where no Hardware Button press event is used and press back button it goes back to the Menu Screen and not getting terminated as shown in image
Need help.
I also faced the same problem but by using the following piece of code
Application.Current.Exit()
the application shuts down properly.
This is generally not recommended. Think hard about why you want to do this and if it really makes sense. Barring recovering from a failure it usually doesn't. The expected behavior is for the app to work nicely with the process lifetime code. There is typically no downside to keeping the app suspended, and it is much more efficient to resume from suspension than to restart completely. The user can use the built-in options to explicitly close the app if desired.
That said, you can call Windows.UI.Xaml.Application.Exit .
You can use this snippet to make the back button react the same as WP8 on WP8.1. In public App():
#if WINDOWS_PHONE_APP
HardwareButtons.BackPressed += HardwareButtons_BackPressed;
#endif
and in the same scope as App():
#if WINDOWS_PHONE_APP
void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame != null && rootFrame.CanGoBack)
{
e.Handled = true;
rootFrame.GoBack();
}
}
#endif

Allow user to click on a Button of the form when Application is in Pause/Sleep Mode in C# winform Application

I am working on a C# winform application which continuously navigates some links in a webbrowser control and process the data of that webpage. I need to provide two buttons on the form for Pause and Resume.
On click of button the whole application should get pause processing and after that on click of Resume button it should start again.
So to pause the application, on click of Pause button I made thread to sleep for infinite time by following code.
private void Pause_Click(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
}
But this piece of code unable the user to click on Resume Button on form to resume the application. Also I am not getting a perfect piece of code to resume the application on click of Resume Button.
Can Anyone get me the correct solution for this issue ?
Thread.Sleep method yields execution of code to process scheduler and doesn't get it back until specified time passes. Therefore you can't make sleeping thread wake itself up. You can't even make a working thread wake another sleeping thread (to my knowledge).
You need to accomplish your goal differently.
Separate data processing code to separate, worker, method
Run worker method in separate thread
Share a state variable between UI and worker thread. This variable should pass signals on whether execution should be paused.
From UI thread, set pause signals in shared variable as needed
In processing loop, write handler code for stopping processing
I'll post some pseudo code below on how you should do this:
private bool _Paused = false;
private void OnPauseClick()
{
_Paused = true;
}
private void OnResumeClick()
{
_Paused = false;
}
private void OnRunClick()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(WorkerMethod));
}
private void WorkerMethod(object state)
{
...
while (needToDoMoreWork)
{
// do some work here
...
// if pause requested, wait to unpause
while (_Paused)
{
// Sleep for a short time and check again if paused
Thread.Sleep(100);
}
}
}
You'll need to fill in the blanks according to your business needs.
If you put your UI thread to indefinite sleep, you're going to kill your UI indefinitely. Don't do that.
Your application has some mechanism to know it's time to do its navigation and processing, probably a timer of some sort. If it's a timer, just stop it when you pause the application, and start it again when you resume. If it's some other mechanism, you need to stop it,too, but it's hard to tell you how without knowing what that mechanism is.

Categories

Resources