Mickeys
asked on
Events with thread
So then I have two more questions. (sorry)
1. If I run this example I can press subscribe...the clock starts......I press unsubscribe and the clock stops. Why Aint I able to press subscribe again and it will start ticking again?
2. Is it possible to make a "start form" from where I can fire this Form1 I have now? That means I can fire up alot of diffrent Form1
1. If I run this example I can press subscribe...the clock starts......I press unsubscribe and the clock stops. Why Aint I able to press subscribe again and it will start ticking again?
2. Is it possible to make a "start form" from where I can fire this Form1 I have now? That means I can fire up alot of diffrent Form1
Clock.CS:
______________________________
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Modul3_Malmoe
{
public class Clock
{
// Private Fields holding the hour, minute and second
private int _hour;
private int _minute;
private int _second;
private bool IsSubscribed;
private bool _bSubscribe;
// The delegate named SecondChangeHandler, which will encapsulate
// any method that takes a clock object and a TimeInfoEventArgs
// object as the parameter and returns no value. It's the
// delegate the subscribers must implement.
public delegate void SecondChangeHandler(object clock, TimeInfoEventArgs timeInformation);
// The event we publish
public event SecondChangeHandler SecondChange;
public Clock()
{
_bSubscribe = true;
}
#region Egenskaper
#endregion
// The method which fires the Event
protected void OnSecondChange(object clock, TimeInfoEventArgs timeInformation)
{
// Check if there are any Subscribers
if (SecondChange != null)
{
// Call the Event
SecondChange(clock, timeInformation);
}
}
/// <summary>
/// only changing private field _bSubscribe
/// </summary>
public void unsunscribe()
{
_bSubscribe = false;
}
// Set the clock running, it will raise an
// event for each new second
public void Run(System.Windows.Forms.TextBox timeTextBox)
{
for (; ; )
{
// Sleep 1 Second
Thread.Sleep(1000);
// Get the current time
System.DateTime dt = System.DateTime.Now;
// If the second has changed
// notify the subscribers
if (dt.Second != _second)
{
int hours = dt.Hour;
string hh1 = Convert.ToString(hours / 10);
string hh2 = Convert.ToString(hours % 10);
string hh3 = hh1 + hh2;
int minute = dt.Minute;
string mm1 = Convert.ToString(minute / 10);
string mm2 = Convert.ToString(minute % 10);
string mm3 = mm1 + mm2;
int seconds = dt.Second;
string ss1 = Convert.ToString(seconds / 10);
string ss2 = Convert.ToString(seconds % 10);
string ss3 = ss1 + ss2;
// Create the TimeInfoEventArgs object
// to pass to the subscribers
TimeInfoEventArgs timeInformation = new TimeInfoEventArgs(Convert.ToInt32(hh3), Convert.ToInt32(mm3), Convert.ToInt32(ss3));
// update the state
_second = dt.Second;
_minute = dt.Minute;
_hour = dt.Hour;
// If anyone has subscribed, notify them
if (_bSubscribe) // if it is subscribed then show in textBox
{
OnSecondChange(this, timeInformation);
}
else
return; // this will end your for loop
}
}
}
}
}
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.Windows.Forms;
using System.Threading;
namespace Modul3_Malmoe
{
public partial class Form1 : Form
{
// Create a new clock
Clock theClock;
private bool flag = true;
// Create the display
private DisplayClock dc = new DisplayClock();
// Create a Log object and tell it
LogClock lc = new LogClock();
public Form1()
{
InitializeComponent();
theClock = new Clock();
unsubscribeButton.Enabled = false;
theClock.SecondChange += new Clock.SecondChangeHandler(theClock_SecondChange);
}
void theClock_SecondChange(object clock, TimeInfoEventArgs timeInformation)
{
MethodInvoker mi = delegate()
{
timeTextBox.Text = timeInformation.hour.ToString() + "." +
timeInformation.minute.ToString() + "." +
timeInformation.second.ToString();
timeTextBox.Parent.Update();
};
updateUI(mi);
}
private void updateUI(MethodInvoker mi)
{
if (this.InvokeRequired)
this.Invoke(mi);
else
mi();
}
private void subscribeButton_Click(object sender, EventArgs e)
{
subscribeButton.Enabled = false;
unsubscribeButton.Enabled = true;
// subscribe to the clock just created
dc.Subscribe(theClock);
// to subscribe to the clock
lc.Subscribe(theClock);
// Get the clock started
MethodInvoker mi = delegate()
{
theClock.Run(timeTextBox);
};
mi.BeginInvoke(null, null);
}
private void unsubscribeButton_Click(object sender, EventArgs e)
{
//theClock.Subscribed = false;
theClock.unsunscribe();
unsubscribeButton.Enabled = false;
subscribeButton.Enabled = true;
}
}
}
ASKER
This is great now I start to understand.
So lets say I have done a startup form with a button called START
How can I then fire up multiplie FORM1?
I mean if I press once I want to start one FORM1. If I press again a new one starts.
Is it
Form1 myform = new Form1()
and then????
So lets say I have done a startup form with a button called START
How can I then fire up multiplie FORM1?
I mean if I press once I want to start one FORM1. If I press again a new one starts.
Is it
Form1 myform = new Form1()
and then????
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thx for everything.
doesn't. This means that when you click on subscribe again then you will have the event registered twice.
For this we will do:
private void unsubscribeButton_Click(ob
{
theClock.unsunscribe();
unsubscribeButton.Enabled = false;
subscribeButton.Enabled = true;
// unsubscribe to the clock just created
dc.UnSubscribe(theClock);
// to unsubscribe to the clock
lc.UnSubscribe(theClock);
}
This still doesn't solve the problem that you have.
Furthermore, you are doing a loop using for but without a start or end index... so why using a for while you can use a While?
while (_bSubscribe)
{
// Sleep 1 Second
Thread.Sleep(1000);
// Get the current time
System.DateTime dt = System.DateTime.Now;
// If the second has changed
// notify the subscribers
if (dt.Second != _second)
{
int hours = dt.Hour;
string hh1 = Convert.ToString(hours / 10);
string hh2 = Convert.ToString(hours % 10);
string hh3 = hh1 + hh2;
int minute = dt.Minute;
string mm1 = Convert.ToString(minute / 10);
string mm2 = Convert.ToString(minute % 10);
string mm3 = mm1 + mm2;
int seconds = dt.Second;
string ss1 = Convert.ToString(seconds / 10);
string ss2 = Convert.ToString(seconds % 10);
string ss3 = ss1 + ss2;
// Create the TimeInfoEventArgs object
// to pass to the subscribers
TimeInfoEventArgs timeInformation = new TimeInfoEventArgs(Convert.
// update the state
_second = dt.Second;
_minute = dt.Minute;
_hour = dt.Hour;
// If anyone has subscribed, notify them
if (_bSubscribe) // if it is subscribed then show in textBox
{
OnSecondChange(this, timeInformation);
}
}
}
The reason why the loop doesn't restart is because bSubscribe is false. You set it to tru when you create the clock object, and set it to false when you unsubscribe.
But you don't set it to true again.
So we will change the Run Function (Since it acts like a subscrube):
public void Run()
{
_bSubscribe = true;
while (_bSubscribe)
{
// Sleep 1 Second
Thread.Sleep(1000);
// Get the current time
System.DateTime dt = System.DateTime.Now;
// If the second has changed
// notify the subscribers
if (dt.Second != _second)
{
int hours = dt.Hour;
string hh1 = Convert.ToString(hours / 10);
string hh2 = Convert.ToString(hours % 10);
string hh3 = hh1 + hh2;
int minute = dt.Minute;
string mm1 = Convert.ToString(minute / 10);
string mm2 = Convert.ToString(minute % 10);
string mm3 = mm1 + mm2;
int seconds = dt.Second;
string ss1 = Convert.ToString(seconds / 10);
string ss2 = Convert.ToString(seconds % 10);
string ss3 = ss1 + ss2;
// Create the TimeInfoEventArgs object
// to pass to the subscribers
TimeInfoEventArgs timeInformation = new TimeInfoEventArgs(Convert.
// update the state
_second = dt.Second;
_minute = dt.Minute;
_hour = dt.Hour;
// If anyone has subscribed, notify them
if (_bSubscribe) // if it is subscribed then show in textBox
{
OnSecondChange(this, timeInformation);
}
}
}
}
I've removed the Textbox from the arguments of the Run since we don't need it anymore and I've also put a _bSubscribe = true before the loop starts.
This answers Q1.
Q2, yes.
each form will have it's own clock objects so you can have multiple forms.