Second form doesn't load properly - c#

I am trying to create an alarm clock and I want a second form to show when the alarm starts.
The problem is that it partialy loads and I get the loading cursor when I hover over it. At first I though I should just wait but nothing changes.
this is how it should be:
this is the function that calls the second form:
private void ring()
{
if (System.DateTime.Now.ToString("HH:mm") == temp && songisplaying == false)
{
soundplayer.PlayLooping();
songisplaying = true;
if (WindowState == FormWindowState.Minimized)
{
this.Show();
WindowState = FormWindowState.Normal;
}
wakeupForm win = new wakeupForm();
win.Show();
}
This is the code of the second form
public partial class wakeupForm : Form
{
public wakeupForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
}
}
This is the code that calls the ring function:
public Form1()
{
InitializeComponent();
num1.Maximum = 2;
num3.Maximum = 5;
num4.Maximum = 9;
var timer2 = new System.Threading.Timer(e => ring(),null,TimeSpan.Zero,TimeSpan.FromSeconds(10));
ofd.Filter = "WAV | *.wav";
}

System.Threading.Timer runs ring() on a thread from the thread pool. ring() in turn tries to instantiate a form which should always be done on the main thread (all access to windows forms should be done from the main thread).
Use the following instead:
private void ring()
{
if (System.DateTime.Now.ToString("HH:mm") == temp && songisplaying == false)
{
songisplaying = true;
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(()=>{ringOnMainThread()}));
else
ringOnMainThread();
}
}
private void ringOnMainThread()
{
soundplayer.PlayLooping();
timer1.Start();
if (WindowState == FormWindowState.Minimized)
{
this.Show();
WindowState = FormWindowState.Normal;
}
wakeupForm win = new wakeupForm();
win.Show();
}
Note that I have moved songisplaying = true; to avoid a race condition.

I believe that you should stop your timer when the form is shown.
(Check your timer interval. If it ticks more than one time in one minute, it will hit your ring() method more than one time).
You should stop your timer in the ring() method and restart on FormClosing of your wakeupForm.
private void ring() {
if (System.DateTime.Now.ToString("HH:mm") == temp && songisplaying == false) {
soundplayer.PlayLooping();
timer1.Stop();//Stop your timer.
songisplaying = true;
if (WindowState == FormWindowState.Minimized)
{
this.Show();
WindowState = FormWindowState.Normal;
}
wakeupForm win = new wakeupForm();
win.Form_Closed += win_Closed;
win.Show();
}
private void wnd_Closed(object sender, EventArgs e)
{
timer1.Start();
}

Related

Nothing happens when I close maximized MDI child form

I have Form1 with 2 radio buttons (rb1 and rb2) and one ordinary button (btn). When I click on btn I should open Form2, as MDI child of Form1 if rb1 is checked, or as ordinary Dialog if rb2 is checked. Also, there can only be one Form2 opened at any moment.
This is my code:
public partial class Form1 : Form
{
Form2 f2;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (f2 != null)
{
MessageBox.Show("Close form!");
return;
}
f2 = new Form2();
if (radioButton1.Checked == true)
{
this.IsMdiContainer = true;
f2.MdiParent = this;
f2.Show();
}
else
{
f2.Show();
}
f2.FormClosed += f2_FormClosed;
}
void f2_FormClosed(object sender, FormClosedEventArgs e)
{
this.IsMdiContainer = false;
f2 = null;
}
}
Everything works as it should except when I maximize Form2 as MDI child and then close it. After that screen stays the same (as I even didn't closed Form2) but I am able to open new Form2, and then Form1's title is "Form1 - [Form2]", and if I repeat the process it would be "Form1 - [Form2] - [Form2]", etc.
I figured out that I my f2_FormClosed method should be
void f2_FormClosed(object sender, FormClosedEventArgs e)
{
f2.Hide(); // <<<<<<<<-----------NEW
this.IsMdiContainer = false;
f2 = null;
}
but I don't know why; Form2 should be closed, I don't know why should I have to hide it?!
Thanks!
I agree with Hans, switching IsMdiContainer at run-time is wonky and is likely to produce other side-effects you haven't seen yet.
Seriously consider a different design for your app.
With that in mind, here's probably the stupidest hack I'll post all day:
public partial class Form1 : Form
{
Form2 f2;
System.Windows.Forms.Timer tmr = new System.Windows.Forms.Timer();
public Form1()
{
InitializeComponent();
tmr.Interval = 100;
tmr.Enabled = false;
tmr.Tick += delegate (object sender, EventArgs e) {
tmr.Stop();
this.IsMdiContainer = false;
};
}
private void button1_Click(object sender, EventArgs e)
{
if (f2 != null)
{
MessageBox.Show("Close form!");
return;
}
f2 = new Form2();
f2.FormClosed += delegate(object sender2, FormClosedEventArgs e2) {
f2 = null;
};
if (radioButton1.Checked == true)
{
this.IsMdiContainer = true;
f2.FormClosed += delegate(object sender3, FormClosedEventArgs e3) {
tmr.Start();
};
f2.MdiParent = this;
}
f2.Show();
}
}
*I originally tried Invoking the call to change IsMdiContainer but that didn't work, so I switched to the Timer. Stupidity that works. Use this solution with caution...

"drag and drop to form" timer in visual studio express 2013 doesn't work

I have no idea why this code does not work.
The timer just seams to freeze everything. As far as I know, the timer is sent to a newly created thread. I've tried locking on tick, but no luck.
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public int CountUp = 0;
public Form1()
{
InitializeComponent();
label1.Text = "Click To Start Timer";
timer1.Enabled = false;
timer1.Stop();
timer1.Interval = 1000;
}
private void button1_Click(object sender, EventArgs e)
{
bool Toggled = false;
if (!Toggled)
{
timer1.Enabled = true;
Toggled = true;
}
else
{
timer1.Enabled = false;
Toggled = false;
label1.Text = "Timer Stopped";
CountUp = 0;
}
while(Toggled){
label1.Text = "Timer1 Running";
}
}
private void timer1_Tick(object sender, EventArgs e)
{
//lock (label2.Text) <- froze the program immediately
//{
// CountUp++;
// string CurrentTime = CountUp.ToString();
// label2.Text = CurrentTime;
//}
CountUp++;
string CurrentTime = CountUp.ToString();
label2.Text = CurrentTime;
//CurrentTime = timer1.ToString() = Garbage & freeze.
}
}
}
Any suggestions? It may be the key to solving this question.
The while(Toggled){ .. } code will freeze the interface and hang the program as it blocks the UI thread. However, the Forms.Timer, which relies on the UI event queue being processed, will never fire due to the blocking loop - as such, the flag variable will never be "reset".
While one of the threaded timers could be used, it would still result in an un-responsive UI. The solution is to design [WinForm] programs to react to events, such as when the timer starts and when it stops1.
1 There are actually no start/stop events per-se, but do the actions when the timer is started or stopped by the code. For example,
private void button1_Click(object sender, EventArgs e)
{
if (!timer1.Enabled) {
CountUp = 0;
timer1.Enabled = true;
label1.Text = "Timer1 Running";
} else {
timer1.Enabled = false;
label1.Text = "Timer1 Stopped (Manual)";
}
}
// Later on, when a tick occurs and the timer should end..
// The timer callback runs on the UI thread it was created on.
private void timer1_Tick(object sender, EventArgs e)
{
CountUp++;
if (CountUp > 10) {
timer1.Enabled = false;
label1.Text = "Timer1 Stopped (Time up)";
}
}
There is no need to use lock at all because all of the code should be running on the UI thread.

How to update a listbox dynamically?

I am making a search utility and using a BackgroundWorker to search. I want that as soon as the first result is found , a new window should open up with a ListBox with the first element displayed. Now, I want that as soon as subsequent results are found, the ListBox should be updated with those results.
The method thought by me was to report the progress as soon as results are found and pass "New" and "Update" as userState to the method.
Based on the userState, I can decide whether to create a new Form or update and existing one.
Here is the code :-
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.UserState.ToString() == "New")
{
Form ResultForm = new Form();
ResultForm.Name = "ResultForm" + i.ToString();
LastFormName = ResultForm.Name;
ListBox ResultListBox = new ListBox();
ResultListBox.DataSource = SearchList;
ResultListBox.Name = "ResultListBox" + i.ToString();
LastListName = ResultListBox.Name ;
ResultForm.Container.Add(ResultListBox);
ResultListBox.Show();
ResultForm.Show();
i++;
}
else
{
;
}
}
I have stored the names of the Last open Form and it's ListBox in the variables LastFormName and 'LastListName'.
I am unable to understand what to put in the else condition, so as to update the ListBox.
What I would do is expose some properties on the popup form so that you can tell if it is open and have access to the list box.
public partial class Popup : Form
{
public bool isOpen;
public ListBox PopupListBox;
public Popup()
{
InitializeComponent();
}
void Popup_FormClosing(object sender, FormClosingEventArgs e)
{
isOpen = false;
}
private void Popup_Load(object sender, EventArgs e)
{
this.FormClosing += Popup_FormClosing;
PopupListBox = popupListBox;
}
}
Then on the calling form I would subscribe to the ProcessedChanged Event and update the listbox with the data you are passing through the ProcessedChangedEventArgs. Here is the code for the calling form
public partial class Form1 : Form
{
Popup popupForm = new Popup();
BackgroundWorker backgroundWorker = new BackgroundWorker();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
backgroundWorker.WorkerSupportsCancellation = true;
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.DoWork += backgroundWorkerDoWork;
backgroundWorker.ProgressChanged += backgroundWorkerProgressChanged;
backgroundWorker.RunWorkerCompleted += backgroundWorkerRunWorkerCompleted;
}
void backgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if ((e.Cancelled == true))
{
//What do you want to do if Cancelled?
}
else if (!(e.Error == null))
{
//What do you want to do if there is an error?
}
else
{
//What do you want to do when it is done?
}
}
void backgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (!popupForm.isOpen || popupForm == null)
{
popupForm = new Popup();
popupForm.Show();
popupForm.isOpen = true;
}
else
{
popupForm.Activate();
popupForm.WindowState = FormWindowState.Normal;
}
popupForm.PopupListBox.Items.Add(e.ProgressPercentage.ToString() + "%");
}
void backgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; (i <= 10); i++)
{
if ((worker.CancellationPending == true))
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(500);
worker.ReportProgress((i * 10));
}
}
}
private void buttonStart_Click(object sender, EventArgs e)
{
if (backgroundWorker.IsBusy != true)
{
backgroundWorker.RunWorkerAsync();
}
}
private void buttonCancel_Click(object sender, EventArgs e)
{
if (backgroundWorker.WorkerSupportsCancellation == true)
{
backgroundWorker.CancelAsync();
}
}
}
You shouldn't be doing work in the ProgressChanged event handler
You won't have access to the results as it is only passed an int for progress and user state
This is on the UI thread. The entire point is to do your processing on a background thread
The name DoWork event handler is clear that this is where you should do your processing.
In answer to your question. Since you create the ListBox in your event handler it goes out of scope outside the if statement. You need to create this in a more global scope. Then to add to it ResultListBox.Items.Add("ResultListBox" + i.ToString());

How to determine that a thread is finished using c#?

I am working with threads in C#. Below is the code which I am using
// worker thread
Thread m_WorkerThread;
// events used to stop worker thread
ManualResetEvent m_EventStopThread;
ManualResetEvent m_EventThreadStopped;
private void btnSend_Click(object sender, EventArgs e)
{
if (btnSend.Text == "Cancel")
{
StopThread();
btnSend.Text = "Send";
return;
}
else
{
// initialize events
m_EventStopThread = new ManualResetEvent(false);
m_EventThreadStopped = new ManualResetEvent(false);
btnSend.Text = "Cancel";
// reset events
m_EventStopThread.Reset();
m_EventThreadStopped.Reset();
// create worker thread instance
m_WorkerThread = new Thread(new ThreadStart(this.ThreadFunction));
m_WorkerThread.Name = "Thread Sample"; // looks nice in Output window
m_WorkerThread.Start();
}
}
private void StopThread()
{
if (m_WorkerThread != null && m_WorkerThread.IsAlive) // thread is active
{
// set event "Stop"
m_EventStopThread.Set();
// wait when thread will stop or finish
try
{
Thread.Sleep(1000);
m_WorkerThread.Abort();
m_WorkerThread.Suspend();
}
catch { }
}
ThreadFinished(); // set initial state of buttons
return;
}
private void ThreadFunction()
{
// Doing My Work
}
private void ThreadFinished()
{
btnSend.Text = "Send";
}
The code above is working fine, but I have some problems.
When the threads end, btnSend.Text = "Send" is not setting.
When I press cancel, the the threads are not ending properly.
When I press cancel and close my application, the application keeps running in the background.
How can I fix these problems?
This is an example of how to use a BackgroundWorker with cancellation:
public partial class Form1 : Form
{
bool _isWorking = false;
public Form1()
{
InitializeComponent();
backgroundWorker1.DoWork += backgroundWorker1_DoWork;
backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
backgroundWorker1.WorkerSupportsCancellation = true;
}
private void button1_Click(object sender, EventArgs e)
{
if (_isWorking)
{
// Cancel the worker
backgroundWorker1.CancelAsync();
button1.Enabled = false;
return;
}
_isWorking = true;
button1.Text = "Cancel";
backgroundWorker1.RunWorkerAsync();
}
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
for (var i = 0; i < 10; i++)
{
if (backgroundWorker1.CancellationPending) { return; }
Thread.Sleep(1000);
}
e.Result = "SomeResult";
}
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
_isWorking = false;
button1.Enabled = true;
button1.Text = "Run";
if (e.Cancelled) return;
// Some type checking
string theResult = e.Result as string;
if (theResult == null) return; // Or throw an error or whatever u want
MessageBox.Show(theResult);
}
}

Countdown after clicking a button that goes from 10 to 0 setting text on a label C#

My problem is very simple but I can't figure it out, so I need your help.
The problem is that I have a button and a label in a form, I simply want to click the button and see the label countdown from 10 to 0 and after that happens the form closes, that simple, can someone help me with this?
BTW, my real app is a form that shows video in real time from my webcam and the idea is to click the button, see the count down and when it finishes the appp saves the current frame as an image.
Thanks in advice!
It sounds like you probably just need three things:
A counter in your class as an instance variable
A timer (System.Windows.Forms.Timer or a DispatcherTimer depending on what UI framework you're using)
A method handling the timer's Tick even which decrements the counter, updates the UI, and stops the timer + takes a snapshot if the counter reaches 0
You can do all of this without any other threads.
Using WindowsFormsApplication u can do it like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
timer1.Enabled = false; // Wait for start
timer1.Interval = 1000; // Second
i = 10; // Set CountDown Maximum
label1.Text = "CountDown: " + i; // Show
button1.Text = "Start";
}
public int i;
private void button1_Click(object sender, EventArgs e)
{
// Switch Timer On/Off
if (timer1.Enabled == true)
{ timer1.Enabled = false; button1.Text = "Start"; }
else if (timer1.Enabled == false)
{ timer1.Enabled = true; button1.Text = "Stop"; }
}
private void timer1_Tick(object sender, EventArgs e)
{
if (i > 0)
{
i = i - 1;
label1.Text = "CountDown: " + i;
}
else
{ timer1.Enabled = false; button1.Text = "Start"; }
}
}
You only need a label, a button and a timer.
use this code. put one timer,label and button.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
timer1.Tick += new EventHandler(timer1_Tick);
}
private static int i = 10;
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "10";
timer1.Interval = 1000;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
label1.Text = (i--).ToString();
if (i < 0)
{
timer1.Stop();
}
}
}

Categories