WinForms sometimes appear twice and sometimes once - c#

I am confuse at this one, the windows form called "Contact" sometimes called twice after the "Welcome Screen" and sometimes it ("Contact") is called once only. I am pretty sure that I called the form once only.
Here is the code that I am using:
The form below "WelcomeScreen" is the first one called when run the program:
public partial class WelcomeScreen : Form
{
int timeLeft = 5;
Timer _timer = new Timer();
BackgroundWorker _backgroundWorker = new BackgroundWorker();
public WelcomeScreen()
{
InitializeComponent();
_backgroundWorker.WorkerReportsProgress = true;
_backgroundWorker.DoWork += BackgroundWorker_DoWork;
_backgroundWorker.ProgressChanged += BackgroundWorker_ProgressChanged;
_timer.Interval = 1000;
_timer.Tick += Timer_Tick;
}
void WelcomeScreen_Load(object sender, EventArgs e)
{
_backgroundWorker.RunWorkerAsync();
}
void Timer_Tick(object sender, EventArgs e)
{
timeLeft--;
if (timeLeft <= 0)
{
_timer.Stop();
this.Hide();
Contact _contact = new Contact();
_contact.ShowDialog();
this.Close();
}
}
void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
if (e.ProgressPercentage <= 300)
{
_timer.Start();
this.label3.Text = "Completed ( " + timeLeft + " ) ";
this.label4.Text = string.Empty;
}
}
void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i <= 300; i++)
{
_backgroundWorker.ReportProgress(i);
System.Threading.Thread.Sleep(200);
}
}
The form below "Contact" is called after the "WelcomeScreen":
public partial class Contact : Form
{
const int CP_NOCLOSE_BUTTON = 0x200;
public Contact()
{
InitializeComponent();
}
void Contact_Load(object sender, EventArgs e)
{
SystemManager.SoundEffect();
}
void button1_Click(object sender, EventArgs e)
{
this.Hide();
Loading _loading = new Loading();
_loading.ShowDialog();
this.Close();
}
protected override CreateParams CreateParams
{
get
{
CreateParams myCp = base.CreateParams;
myCp.ClassStyle = myCp.ClassStyle | CP_NOCLOSE_BUTTON;
return myCp;
}
}
I appreciate your answer!
Thank you

It looks like your Timer is causing the issue, by firing multiple times...
You have this condition inside your timer code:
if (timeLeft <= 0)
And the line before is timeLeft--. After timeLeft becomes 0, it will continue getting smaller (-1, -2, etc) and the form will be shown each time.
A quick fix is to either change the condition to timeLeft == 0 or change the type of timeLeft to a uint. Of course, these are both hacks. The correct fix would be to fix your code to stop the timer from firing when required.

Related

How to use progressbar.value property at different locations of program

I need to use progressbar.value property at different locations. But the problem is, while executing it shows only maximum value given. I need to stop at 25% and 75% and after some delay, 100%. How can I overcome this problem. Thanks in Advance...
C#
namespace ProgressBarWindowForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void Form1_Load(object sender, System.EventArgs e)
{
label1.Hide();
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;
}
private void button1_Click(object sender, EventArgs e)
{
progressBar1.Value = 25;
if (progressBar1.Value == 25)
{
label1.Show();
label1.Text = "Process Complete 25%";
}
progressBar1.Value = 75;
if (progressBar1.Value == 75)
{
label1.Show();
label1.Text = "Process Complete 75%";
}
}
}
}
Progressbar control name is progressBar1,
Label name is label1 and
Button name is button1
When I Clicked the Button, progressbar value is directly filling with 75%. I want to stop it at 25% and after some delay it should fill 75% and then 100%...Can anyone help..Can I use "progressBar1.value" only Once or as many times I need?
try this,Drag and drop background worker in windows form
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
// This event will be raised on the worker thread when the worker starts
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
// This event will be raised when we call ReportProgress
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
}
private void button1_Click(object sender, EventArgs e)
{
// Start the background worker
backgroundWorker1.RunWorkerAsync();
}
// On worker thread so do our thing!
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// Your background task goes here
for (int i = 0; i <= 100; i++)
{
// Report progress to 'UI' thread
backgroundWorker1.ReportProgress(i);
// Simulate long task
if (label1.InvokeRequired)
{
label1.Invoke(new MethodInvoker(delegate
{
label1.Show();
label1.Text = "Process Complete " + progressBar1.Value + "%";
}));
}
if (progressBar1.Value == 25 || progressBar1.Value == 75)
{
System.Threading.Thread.Sleep(1000);
}
System.Threading.Thread.Sleep(100);
}
}
// Back on the 'UI' thread so we can update the progress bar
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// The progress percentage is a property of e
progressBar1.Value = e.ProgressPercentage;
}
}
Use a Timer to update the progress bar after a delay:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
timer.Tick += Timer_Tick;
timer.Interval = 1000; // delay: 1000 milliseconds
}
Timer timer = new Timer();
private void Timer_Tick(object sender, EventArgs e)
{
if (progressBar1.Value == 100)
{
timer.Stop();
return;
}
progressBar1.Value += 25;
}
private void button1_Click(object sender, EventArgs e)
{
progressBar1.Value = 25;
timer.Start();
}
}
Its simple to update progressBar values in button click, you can initialize the properties in the page load or else use the designer, in page load it would be like the following:
private int ProgressPercentage = 10;
public void Form1_Load(object sender, System.EventArgs e)
{
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;
progressBar1.Value = 0;
}
So the initialization completed, now you can code the button click like the following, through which you can update the progress bar in every button click:
private void button1_Click(object sender, EventArgs e)
{
progressBar1.Value += ProgressPercentage;
label1.Text = String.Format("Process Complete {0}%",progressBar1.Value);
}
If you want the update to be happens automatically in a particular interval means you can make use of a timer and enable the timer in the button click. Here you can find a similar thread which can be used to implement timer to your scene.
Update as per your comment, calling a delay will not be a best practice, you can make use a timer here as like the following:
System.Windows.Forms.Timer proTimer = new System.Windows.Forms.Timer();
private void Form1_Load(object sender, EventArgs e)
{
proTimer.Interval = 1000;
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;
progressBar1.Value = 0;
proTimer.Tick += new EventHandler(proTimer_Tick);
}
private void button1_Click(object sender, EventArgs e)
{
proTimer.Enabled = true;
proTimer.Start();
}
// Timer event
void proTimer_Tick(object sender, EventArgs e)
{
progressBar1.Value += ProgressPercentage;
label1.Text = String.Format("Process Complete {0}%",progressBar1.Value);
if (progressBar1.Value == 100)
{
proTimer.Stop();
proTimer.Enbled = false;
}
}
You need to add a delay inbetween the changes. As of now, the button advance the bar to 25, sets the label, then advances the bar to 75 without pausing.
System.Threading.Thread.Sleep(n); will sleep n milliseconds, which you will need after the statement setting the 25 percent marker.
EDIT
If you want it the value to only progress on a button click, you will need to check the value of the progress bar before you advance it.
In pseudo code, something like:
onclick() {
if (progress == 0) {
progress = 25
label = the25MarkText
} else if (progress == 25) {
progress = 75
label = the75MarkText
}
}

c# real time update a chart

Here I have a chart (graph1) that normally should add a random point every 1second. but it doesn't... I tried to find out what the problem is but here I don't have anymore ideas...
The timer is started, label1 change every seconds but the chart doesn't change... with button one when I click it adds a new point.
what did I miss? please help... thanks a lot.
namespace Test_Chart1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
graph1.ChartAreas[0].AxisX.ScrollBar.Enabled = true;
graph1.ChartAreas[0].AxisX.IsLabelAutoFit = true;
graph1.ChartAreas[0].AxisX.ScaleView.Size = 40;
System.Timers.Timer _Timer1s = new System.Timers.Timer(1000); //object
_Timer1s.Elapsed += _Timer1sElapsed; //event in object
_Timer1s.Start(); //start counting
}
private void _Timer1sElapsed(object sender, EventArgs e)//Timer each 100ms
{
if (label1.BackColor == Color.Red)
{
label1.BackColor = Color.Blue;
PutValueInGraph1();
}
else label1.BackColor = Color.Red;
}
private void button1_Click(object sender, EventArgs e)
{
PutValueInGraph1();
}
private void PutValueInGraph1()
{
graph1.ChartAreas[0].AxisX.ScrollBar.Enabled = true;
graph1.ChartAreas[0].AxisX.IsLabelAutoFit = true;
graph1.ChartAreas[0].AxisX.ScaleView.Size = 100;
Random Rand_Value = new Random();
int ValueToAdd = Rand_Value.Next(1, 100);
listBox1.Items.Add(ValueToAdd.ToString());
graph1.Series["Data1"].Points.AddY(ValueToAdd);
if (graph1.ChartAreas[0].AxisX.Maximum-10 > graph1.ChartAreas[0].AxisX.ScaleView.Size)
{
graph1.ChartAreas[0].AxisX.ScaleView.Scroll(graph1.ChartAreas[0].AxisX.Maximum);
graph1.Series["Data1"].Points.RemoveAt(0);
}
}
}
}
ok here is the new one:
public partial class Form1 : Form
{
static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();
public Form1()
{
InitializeComponent();
myTimer.Tick += new EventHandler(TimerEventProcessor);
myTimer.Interval = 1;
}
private void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
{
Random Rand_Value = new Random();
int ValueToAdd = Rand_Value.Next(1, 100);
listBox1.Items.Add(ValueToAdd.ToString());
graph1.Series["Data1"].Points.AddY(ValueToAdd);
if (graph1.ChartAreas[0].AxisX.Maximum - 10 > graph1.ChartAreas[0].AxisX.ScaleView.Size)
{
graph1.ChartAreas[0].AxisX.ScaleView.Scroll(graph1.ChartAreas[0].AxisX.Maximum);
graph1.Series["Data1"].Points.RemoveAt(0);
}
}
private void btn_Start_Click_1(object sender, EventArgs e)
{
graph1.ChartAreas[0].AxisX.ScrollBar.Enabled = true;
graph1.ChartAreas[0].AxisX.IsLabelAutoFit = true;
graph1.ChartAreas[0].AxisX.ScaleView.Size = 100;
myTimer.Start();
BlinkLed.BackColor = Color.YellowGreen;
}
private void btn_Stop_Click(object sender, EventArgs e)
{
myTimer.Stop();
BlinkLed.BackColor = Color.AliceBlue;
}
}
Do you think it's better?
What about the changing thread?
If I had a button:
private void PutValueInGraph1()
{
Random Rand_Value = new Random();
int ValueToAdd = Rand_Value.Next(1, 100);
listBox1.Items.Add(ValueToAdd.ToString());
graph1.Series["Data1"].Points.AddY(ValueToAdd);
if (graph1.ChartAreas[0].AxisX.Maximum-10 > graph1.ChartAreas[0].AxisX.ScaleView.Size)
{
graph1.ChartAreas[0].AxisX.ScaleView.Scroll(graph1.ChartAreas[0].AxisX.Maximum);
graph1.Series["Data1"].Points.RemoveAt(0);
}
}
private void button1_Click(object sender, EventArgs e)
{//try to raise exception
PutValueInGraph1();
}
and I change the event like this:
private void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
{//try to raise exception
PutValueInGraph1();
}
The data input accelerate when I'm started the timer and I click all the time on the button1.
Why is there no exception as tom_imk said??
because we can access the same function at the same time....?
Thanks for your answers.
I tried below sample code and it is working fine for me.
public Form7()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
chart1.ChartAreas[0].AxisX.Maximum = 100;
chart1.ChartAreas[0].AxisX.Minimum = 0;
chart1.ChartAreas[0].AxisX.Interval = 1;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
Random Rand_Value = new Random();
int ValueToAdd = Rand_Value.Next(1, 100);
chart1.Series[0].Points.AddY(ValueToAdd);
}
I'm surprised you didn't get an exception. You are manipulating UI elements outside the UI thread, something you musn't do, ever.
Refer to the answer in this question:
How to update the GUI from another thread in C#?
EDIT:
To make clear why the timerelapsed method does not run on the UI thread: It's simply the wrong class that is used here. So the easy solution would be to not created a System.Timers.Timer in the Form-constructor but to drop a timer on the form in the form designer and use that instead. The solution by sowjanya attaluri should be marked as the correct answer.

Form timer doesn't start

So I just started learning C# and using forms. I have been able to create a digital clock and tinker with this and that, but now I'm trying to make a basic UI for a derpy game and my timer doesn't work.
First - what I'm trying to accomplish: A simple decrementing timer from 60 seconds (*clock style (mm:ss)).
Second, here's what I have:
public partial class Form1 : Form
{
private int counter = 60;
public Form1()
{
InitializeComponent();
label1.Text = TimeSpan.FromMinutes(1).ToString("m\\:ss");
}
private void pictureBox2_Click(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
counter--;
if (counter == 0)
{
timer1.Stop();
label1.Text = counter.ToString();
MessageBox.Show("Time's Up!!");
}
}
private void label1_Click(object sender, EventArgs e)
{
var startTime = DateTime.Now;
var counter = (TimeSpan.FromMinutes(1)).ToString("m\\:ss");
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = 1000;
timer1.Start();
label1.Text = counter.ToString();
}
}
Appreciate the feedback and knowledge!
From the codes that I see, your timer is working but you are not updating it in each count, you are updating when the timer finishes -
private void timer1_Tick(object sender, EventArgs e)
{
counter--;
if (counter == 0)
{
timer1.Stop();
label1.Text = counter.ToString(); // *** Look here
MessageBox.Show("Time's Up!!");
}
}
You should update the timer in each tick, so take the update label code out of the if block -
private void timer1_Tick(object sender, EventArgs e)
{
counter--;
label1.Text = counter.ToString(); // should work
if (counter == 0)
{
timer1.Stop();
MessageBox.Show("Time's Up!!");
}
}
and also reset the counter in each cycle -
private void label1_Click(object sender, EventArgs e)
{
var startTime = DateTime.Now;
var counter = (TimeSpan.FromMinutes(1)).ToString("m\\:ss");
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = 1000;
timer1.Start();
label1.Text = counter.ToString();
this.counter = 60
}
NOTE: I am really not sure if this code will throw any access
violation error, due to updating the UI in a different thread or not.
If so, then you have to use async/await or events/delegates to
update UI.
Let me know, if this throws error, then I will give you the async/await version.
This works fine for me. I would give progress updates as the time is countdown to show that it is working. For example, if you did this in label, you could do something like the following:
private void timer1_Tick(object sender, EventArgs e)
{
counter--;
label1.Text = counter.ToString();
if (counter == 0)
{
timer1.Stop();
MessageBox.Show("Time's Up!!");
}
}
Notice that the label1.Text = counter.ToString(); line has been moved before the counter == 0 check, so that it is able to provide feedback for all counter values.
As well, you may accidentally launch several timer1 instances if you do not keep track of how many you spawn using new Timer(). There are various ways to do this, but you could simply check whether timer1 already exists and counter == 0 before creating a new instance. You could perform this check as a guard clause (ie. return if either of those conditions are matched).
private void label1_Click(object sender, EventArgs e)
{
var startTime = DateTime.Now;
if (timer1 == null || (timer1 != null && counter == 0)) return;
counter = (TimeSpan.FromMinutes(1)).ToString("m\\:ss");
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = 1000;
timer1.Start();
label1.Text = counter.ToString();
}
If you want this countdown to start automatically, you can put this directly into the constructor, or put it into another method and call it from the constructor like so:
public Form1()
{
InitializeComponent();
StartCountdown();
}
private void StartCountdown()
{
var startTime = DateTime.Now;
/* the rest of your original label1_Click code goes here ... */
}

how to update a textlabel when a variable is changed

im kinda new to programming, and i was trying to recreate candybox (some interactive website)
in windows form application. i have a variable named candy, and a timer that every second adds one to the variable candy, i have tried putting the label.text = "candy: " + candy.ToString(); in that method and it doesnt seem to work, any one able to help?
code:
public partial class Form1 : Form
{
public int candy { get; set; }
public int lollipop { get; set; }
public Form1(int value, int lollipop)
{
this.candy = value;
this.lollipop = lollipop;
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
label1.Text = "candy: 0";
button2.Enabled = false;
button2.Visible = false;
label2.Visible = false;
timer.Elapsed += new System.Timers.ElapsedEventHandler(this.TimerHandler);
timer.Start();
}
private void button1_Click(object sender, EventArgs e)
{
candy += 2;
UpdateCandy(candy, lollipop);
label2.Text = "lollipops" + lollipop.ToString();
if (candy > 9)
{
button2.Enabled = true;
button2.Visible = true;
}
}
private void button2_Click(object sender, EventArgs e)
{
if (candy <= 10)
{
button2.Enabled = false;
}
candy -= 10;
lollipop += 1;
UpdateCandy(candy, lollipop);
label2.Text = "lollipops" + lollipop.ToString();
label2.Visible = true;
}
System.Timers.Timer timer = new System.Timers.Timer(1000);
private void TimerHandler(object sender, System.Timers.ElapsedEventArgs e)
{
DateTime start;
TimeSpan elapsed = TimeSpan.MaxValue;
while (elapsed.TotalSeconds > 1.0)
{
start = DateTime.Now;
candy += 1;
elapsed = DateTime.Now - start;
}
timer.Interval = 1000 - elapsed.TotalMilliseconds;
timer.Start();
}
public void Form1_Shown(object sender, EventArgs e)
{
timer.Elapsed += new System.Timers.ElapsedEventHandler(this.TimerHandler);
timer.Start();
}
private void UpdateCandy(int candy, int lollipop)
{
label1.Text = "candy: " + candy.ToString();
label2.Text = "lollipops" + lollipop.ToString();
}
}
and im using visual studio 2012 (if this information is of any help)

Timer + display messages + Different time intervals

How to display some messages on a C# form application with different time intervals with buttons?
Something like:
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "string1";
[wait 3 seconds]
label1.Text = "string2";
[wait 5 sec]
label1.text="string 3";
[end]
}
You can create a new thread, change the label text, sleep that thread and so on so forth:
using System.Threading;
// Somewhere in your Form, for example in Form_Load event:
new Thread(new ThreadStart(delegate {
var d = new setLabelTextDelegate(setLabelText);
label1.Invoke(d, new object[] { "string 1" });
Thread.Sleep(3000); // sleep 3 seconds
label1.Invoke(d, new object[] { "string 2" });
Thread.Sleep(5000); // sleep 5 seconds
label1.Invoke(d, new object[] { "string 3" });
})).Start();
private delegate void setLabelTextDelegate(string text);
private void setLabelText(string text)
{
this.label1.Text = text;
}
Use a Timer with an interval of X milliseconds and update the UI each Timer Tick. Keep track of the number of Timer Ticks received so you'll know which string to use. After each update has been processed stop the Timer.
Other solutions posted might be wiser, but this one is pretty simple.
Form1 contains a simple Label called Label1 and a button called Button1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
t.Interval = 100;
t.Tick += new EventHandler(t_Tick);
t.Start();
}
Timer t = new Timer();
int counter = 0;
private void Button1_Click(object sender, EventArgs e)
{
t.Start();
}
void t_Tick(object sender, EventArgs e)
{
try
{
t.Enabled = false; //Disable timer so we don't start t_Tick when t_Tick is still runnnig
if (counter == 0)
{
label1.Text = "string1";
t.Interval = 3000;
}
if (counter == 1)
{
label1.Text = "string2";
t.Interval = 5000;
}
if (counter == 2)
{
label1.Text = "string3";
t.Stop(); //Stop timer
}
else
{
t.Enabled = true; //Resume timer
}
counter++;
}
catch (Exception ex)
{
MessageBox.Show("Never throw exception from timer..." + ex.Message);
}
}
To do exactly as your pseudo code suggest simply use Thread.Sleep() in place of your [wait x] lines. Note that it will likely make UI unresponsive for the duration of waiting.
Alternatively you can create a thread that does the same thing but doesn't block the UI thread. The only issue there is that you have to define delegate in UI thread otherwise it wont work.
private void button1_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(delegate()
{
label1.Text = "string1";
Thread.Sleep(3000);
label1.Text = "string2";
Thread.Sleep(5000);
//etc...
});
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "string1";
System.Threading.Thread.Sleep(3*1000);
label1.Text = "string2";
System.Threading.Thread.Sleep(5*1000);
label1.text="string 3";
}
Thank you sooo much.
Oh i love stakoverflow.com
I did something like this.:)
Thank you all gentle mens :)
Please comment how did i do? I actually wanted it all happen in click of button.
public partial class mainForm : Form {
public mainForm()
Timer myTimer = new Timer();
private void button1_Click(object sender, EventArgs e)
{
myTimer.Tick += new EventHandler(myTimer_Tick);
myTimer.Interval = 2000;
myTimer.Start();
}
int counter=0;
void myTimer_Tick(object sender, EventArgs e)
{
if (counter == 0)
{
label4.Text = "string1";
myTimer.Interval = 2000;
}
if (counter == 1)
{
label4.Text = "string2";
myTimer.Interval = 2000;
}
if (counter == 2)
{
label4.Text = "string3";
myTimer.Stop();
}
else
{
myTimer.Enabled = true;
}
counter++;
} }
I made it all work with valuable examples you all provided . i put it all together and got it working as i wanted.
Once again Thank you all :)

Categories

Resources