Visual Studio C# while loop freezing forms application [duplicate] - c#

This question already has answers here:
Thread.Sleep() in C#
(4 answers)
Closed 6 years ago.
Here's my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace _8BB_2._0
{
public partial class Form1 : Form
{
public static class globalVars
{
public static bool spacerunning = false;
}
public Form1()
{
InitializeComponent();
globalVars.spacerunning = false;
}
private void button1_Click(object sender, EventArgs e)
{
if (!globalVars.spacerunning)
{
globalVars.spacerunning = true;
while (globalVars.spacerunning)
{
Thread.Sleep(1000);
SendKeys.Send(" ");
}
}
else if (globalVars.spacerunning)
{
globalVars.spacerunning = false;
}
}
}
}
When I click button1 it's starts hitting space every second like it should but when I try to click it again to shut it off the application freezes and it keeps pressing space. I've tried multiple other ways but can't seem to figure out how I can do two things at once since I get locked inside of the while loop.

Calling Thread.Sleep() will block the UI thread. Try to use async/await instead.
private async void button1_Click(object sender, EventArgs e)
{
globalVars.spacerunning = !globalVars.spacerunning;
while (globalVars.spacerunning)
{
await Task.Delay(1000);
SendKeys.Send(" ");
}
}
UPDATE:
You may use a Timer instead.
public class MainForm : Form
{
private Timer timer = new Timer() { Interval = 1000 };
public MainForm()
{
/* other initializations */
timer.Enabled = false;
timer.Tick += timer_Tick;
}
private void timer_Tick(object sender, EventArgs e)
{
SendKeys.Send(" ");
}
private void button1_Click(object sender, EventArgs e)
{
globalVars.spacerunning = !globalVars.spacerunning;
timer.Enabled = globalVars.spacerunning;
}
}

Related

Error: "Cross-thread operation not valid" when Form.close() with CefSharp [duplicate]

This question already has answers here:
Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on
(22 answers)
Closed 5 years ago.
I use Cefsharp.Winform (http://cefsharp.github.io/).
I Try Form.Close() but it error:
System.InvalidOperationException: 'Cross-thread operation not valid: Control 'Form2' accessed from a thread other than the thread it was created on.'
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TEST_CEF
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.Show();
}
}
}
Form2.cs
using CefSharp;
using CefSharp.WinForms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TEST_CEF
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
InitBrowser();
}
public ChromiumWebBrowser browser;
public void InitBrowser()
{
Cef.Initialize(new CefSettings());
browser = new ChromiumWebBrowser("www.google.com");
this.Controls.Add(browser);
browser.Dock = DockStyle.Fill;
browser.FrameLoadEnd += WebBrowserFrameLoadEnded;
}
private void WebBrowserFrameLoadEnded(object sender, FrameLoadEndEventArgs e)
{
if (e.Frame.IsMain)
{
if (browser.Address.IndexOf("google") > -1)
{
timer1.Start();
}
}
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
browser.Dispose();
Cef.Shutdown();
}
int time = 0;
private void timer1_Tick(object sender, EventArgs e)
{
time++;
if (time==3)
{
this.Close();
}
}
}
}
Which kind of timer do you use?
Consider using InvokeRequired in the timer1_Tick method.
private void timer1_Tick(object sender, EventArgs e)
{
if (InvokeRequired) { Invoke(new Action(() => { timer1_Tick(sender, e); })); return; }
time++;
if (time==3)
{
this.Close();
}
}
From the docs (emphasis from me):
It's important to note this event is fired on a CEF UI thread, which by default is not the same as your application UI thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang.. To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
So you start the timer in another thread so I suppose the Tick event will be raised in this CEF UI thread, too.
So you must use Invoke if needed:
Action close = () => this.Close();
if (InvokeRequired)
Invoke(close);
else
close();

C# Timer not stopping?

Here's what I have, why is my timer(s) not stopping?
I'm not sure what I'm doing wrong.
I'm fairly new to C# and I'm trying to make it so my splash screen Hides(form1) and my program starts(samptool) however my program starts but the splash screen stays and the timers reset instead of stopping. Every 6.5 seconds the application opens in a new window.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Timers;
namespace SplashScreen.cs
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
timer1.Interval = 250;
timer2.Interval = 6500;
timer1.Start();
timer2.Start();
}
private void pictureBox1_Click(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
this.progressBar1.Increment(5);
}
private void timer2_Tick(object sender, EventArgs e)
{
SampTool w = new SampTool();
Form1 m = new Form1();
timer1.Enabled = false;
timer1.Stop();
timer2.Enabled = false;
timer2.Stop();
m.Hide();
w.Show();
}
}
}
When you use the new keyword, you create a new instance of a class:
Form1 m = new Form1();
When you create a new instance, the constructor is invoked (the constructor is the method that is named the same as the class).
This will run all the code in the constructor again, hence creating new timers.
To close the current form, you should just run the forms Hide method:
private void timer2_Tick(object sender, EventArgs e)
{
timer1.Stop();
timer2.Stop();
SampTool sampTool = new SampTool();
sampTool.Show();
Hide(); // call the Forms Hide function.
}

How can i add to the timer control a propert to display only hours minutes seconds without milliseconds?

In the control designer i have label1.
In the designer the label text is set to: "00:00:00:000"
Then the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace WinFormsUI
{
public partial class TimerControl : UserControl
{
Stopwatch sw = new Stopwatch();
public TimerControl()
{
InitializeComponent();
//Start();
}
public void Start()
{
timer1.Start();
sw.Start();
}
public void Stop()
{
timer1.Stop();
}
public void Reset()
{
sw.Reset();
label1.Text = "00:00:00:000";
}
public void NoMsSecMin()
{
}
private void TimerControl_Load(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
TimeSpan elapsed = sw.Elapsed;
label1.Text = string.Format("{0:00}:{1:00}:{2:00}:{3:00}",
Math.Floor(elapsed.TotalHours),elapsed.Minutes,elapsed.Seconds,
elapsed.Milliseconds);
}
}
}
I added now the method NoMsSecMin
Maybe there is a better way, I want to add a property like Start Stop Reset something that i can easy set if to show or not milliseconds or seconds or minutes.
How can i make it so i will be able to select with this method what not to show or to show ?
You need a function like that?
ShowWhatIWant(true, false, false);
private string ShowWhatIWant(bool showMinutes, bool showSeconds, bool showMiliSeconds)
{
string text = string.Format("{0:00}", Math.Floor(elapsed.TotalHours));
if(showMinutes)
{
text += string.Format(":{0:00}", elapsed.Minutes);
}
if(showSeconds)
{
text += string.Format(":{0:00}", elapsed.Seconds);
}
if(showMiliSeconds)
{
text += string.Format(":{0:00}", elapsed.Milliseconds);
}
return text;
}

Dialogbox doesn't show orginal form

I have a Windows Mobile 6.5 App under development. When the user opens the App a dialog box appears with the login form. User logs in and then after 30 seconds (small time in production) when the timer has run out without activity I show the login Dialog box again using events:
static private void _TimerTick(object state)
{
// the user has been inactive for 30 secs; log him out
MainForm.timer = null;
using (LoginForm LoginForm = new LoginForm())
{
if (LoginForm.ShowDialog() == DialogResult.OK)
{
MainForm.timer = new System.Threading.Timer(_TimerTick, null, 1000 * 30 * 1, Timeout.Infinite);
}
else
{
Application.Exit();
}
}
}
But once I press login and return with an ok button from the login form the original form does show. Although it is still in the task manager. I have tried:
.TopMost = true; but then I can't assess the windows button in the bar at the bottom of the app and no other apps can run as form in my app is always in front of it.
A simple solution as this is only for the login and one main form:
LoginForm.cs (with two textboxes and main menu with Login and Exit):
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace LoginFormTest
{
public partial class LoginForm : Form
{
public LoginForm()
{
InitializeComponent();
}
public void doShow(bool bShow)
{
if(bShow)
Invoke(new Action(() => this.Show()));
else
Invoke(new Action(() => this.Hide()));
}
public void doClose()
{
Invoke(new Action(() => this.Close()));
}
private void mnuLogin_Click(object sender, EventArgs e)
{
MainForm mainForm = new MainForm();
mainForm.Show();
System.Diagnostics.Debug.WriteLine("mainForm started");
}
}
}
Nothing special there.
The MainForm has code that will close the form if no activity:
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace LoginFormTest
{
public partial class MainForm : Form
{
int countDown = 3; //number of seconds for timeout
System.Threading.Timer timer;
object lockCounter = new object(); //to sync access to counter var
public MainForm()
{
InitializeComponent();
//start a independent timer after 1000ms and with a 1000ms interval
timer = new System.Threading.Timer(new TimerCallback(this.timerCallback), null, 1000, 1000);
}
private void mnuExit_Click(object sender, EventArgs e)
{
doClose();
}
private void mnuLogout_Click(object sender, EventArgs e)
{
doClose();
}
private void doClose()
{
System.Diagnostics.Debug.WriteLine("mainForm closing");
try
{
timer.Dispose(); //else timer thread will continue running!
Invoke(new Action(() => this.Close()));
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Exception in doClose(): " + ex.Message);
}
}
private void MainForm_MouseMove(object sender, MouseEventArgs e)
{
resetTimeout();
}
private void MainForm_KeyPress(object sender, KeyPressEventArgs e)
{
resetTimeout();
}
private void MainForm_Click(object sender, EventArgs e)
{
resetTimeout();
}
public void resetTimeout()
{
System.Diagnostics.Debug.WriteLine("resetTimeout()");
lock(lockCounter)
countDown = 3;
}
public void timerCallback(object stateInfo)
{
lock (lockCounter)
countDown--;
if (countDown == 0)
{
System.Diagnostics.Debug.WriteLine("timeout->doClose()");
doClose();
}
}
private void MainForm_Closed(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine("mainForm CLOSED");
}
}
}
Specials:
a lock object to sync access to the counter var
a threading timer that runs independent of the message pump
a delegate to by called from the TimerCallback function

C# - Threading in forms [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to update GUI from another thread in C#?
I have form with textBox1 and textBox2. I need very simple example of an extra thread to fill textBox2, just to understand principle. So far i am using MessageBox to display value, but i want to use textBox2 instead. Here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace Threads_example
{
public partial class Form1 : Form
{
Thread t = new Thread(t1);
internal static int x1 = 1;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
static void t1()
{
do
{
x1++;
MessageBox.Show("x1 - " + x1.ToString());
}
while(x1<10);
}
private void button1_Click(object sender, EventArgs e)
{
t.Start();
for (int x = 1; x < 100000; x++)
{
textBox1.Text = x.ToString();
textBox1.Refresh();
}
}
}
}
You need to invoke UI actions in the GUI thread.
It can be done with something like this:
private void RunFromAnotherThreadOrNot()
{
if (InvokeRequired)
{
Invoke(new ThreadStart(RunFromAnotherThread));
return;
}
textBox2.Text = "What Ever";
// Other UI actions
}

Categories

Resources