DispatcherTimer is not executing code when I add conditions or try and start the timer outside the constructor.
The problem I am having is if I start the DispatchTimer in the constructor without condition my graphics layer adds before button Show_ClickStuff is clicked. If I don't start everything in the constructor and I place my if conditions in the Show_ClickStuff or in _timer_tick I can place Break Points on the code and watch the timer hit the lines of code but will not execute the lines of code. If I remove conditions code will execute. I have tried all kinds of variations and can not get this to work the way I need
using System.Windows.Threading;
.NET Framework 4.5
Code file: .xaml.cs
Silverlight 4
public Tool()
{
InitializeComponent();
_timer1 = new DispatcherTimer();
//_timer1.Start();
_timer1.Interval = TimeSpan.FromMilliseconds(4000);
_timer1.Tick += new EventHandler(_timer_tick);
}
private void Show_ClickStuff(object sender, RoutedEventArgs e)
{
ToggleStuff();
if (showStuff.IsChecked == true)
{
//Timer_Toggle(this, null);
//_timer1 = new DispatcherTimer();
//_timer1.Start();
//_timer1.Interval = TimeSpan.FromMilliseconds(4000);
//_timer1.Tick += new EventHandler(_timer_tick);
_timer1.Start();
}
else if (!_timer1.IsEnabled && showStuff.IsChecked == true)
{
_timer1.Start();
}
else
{
_timer1.Stop();
}
}
private void _timer_tick(object sender, EventArgs e)
{
_map.Layers.Remove(_stuffLayer);
GetStuff();
_map.Layers.Add(_stuffLayer);
}
Related
I have the following code :
public partial class FereastraAlerta : UserControl
{
private static DispatcherTimer dispatcherTimer;
public FereastraAlerta()
{
InitializeComponent();
}
public void InitTimer()
{
dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, Convert.ToInt32(textBox.Text), 0);
dispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
CommandManager.InvalidateRequerySuggested();
Window.GetWindow(this).Show();
}
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key < Key.D0 || e.Key > Key.D9)
{
e.Handled = true;
}
}
private void btnOK_Click(object sender, RoutedEventArgs e)
{
Window.GetWindow(this).Close();
}
private void btnRemind_Click(object sender, RoutedEventArgs e)
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if(Window.GetWindow(this).Title == "ANM")
config.AppSettings.Settings["nIntervalDeTimpReminderANM"].Value = textBox.Text;
else if (Window.GetWindow(this).Title == "CAS")
config.AppSettings.Settings["nIntervalDeTimpReminderCAS"].Value = textBox.Text;
else if (Window.GetWindow(this).Title == "MS")
config.AppSettings.Settings["nIntervalDeTimpReminderMS"].Value = textBox.Text;
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
Window.GetWindow(this).Hide();
InitTimer();
}
}
I open this window with the following :
if (data != strDataCurentaANM)
{
FereastraAlerta win1 = new FereastraAlerta();
Window window1 = new Window
{
Title = "ANM",
Content = win1,
Height = 300,
Width = 300
};
window1.Show();
win1.label.Content = textAvertizare + " " + data;
win1.textBox.Text = ConfigurationManager.AppSettings["nIntervalDeTimpReminderANM"];
strDataCurentaANM = data;
modifica = true;
}
This application check some websites and if the information changed it give me a warning, it have 3 warning windows at the moment and I got this problem:
I open 3 windows and I want them to remind me about the warning in 2 , 4 ,6 min, no problem until here, they will hide and will apear on the screen in that time. But if I try to modify the reminder again it will create another timer or something like this , I don't really understand the behavior.
Also the period that the window will apear it will be much shorter that the time inserted .https://i.stack.imgur.com/gkeu6.png
If I press ok the window should close and they does but the timer is somehow still alive and will try to show the window which I closed so it will generate this error https://i.stack.imgur.com/4dDzJ.png
Ok my guess is that whenever I hit the remind button it will create a new timer and the old one will still run(but this don't explain why sometimes all the windows will popup at once even if the reminder is not the same) and this is right:
What can I do in order to get rid of the old timer and let only the new one.
Also if you can give me any suggestions about how I should improve my code I'm listening .
If I press ok the window should close and they does but the timer is somehow still alive and will try to show the window which I closed so it will generate this error
Unsubscribe the dispatcherTimer_Tick and stop the timer before closing your window
private void btnOK_Click(object sender, RoutedEventArgs e)
{
if (dispatcherTimer != null)
{
dispatcherTimer.Tick -= dispatcherTimer_Tick;
dispatcherTimer.Stop();
}
Window.GetWindow(this).Close();
}
if I try to modify the reminder again it will create another timer
Same thing when you start a new timer
public void InitTimer()
{
if (dispatcherTimer != null)
{
dispatcherTimer.Tick -= dispatcherTimer_Tick;
dispatcherTimer.Stop();
}
Ok my guess is that whenever I hit the remind button it will create a
new timer and the old one will still run
Yes, definitely, each time you call InitTimer() you create a new timer. But also you didn't kill the old one, and it wont be garbage collected because it has an event subscription.
Thus each time it creates a new timer and they all tick whenever they should.
To avoid that, you have to be carefull with subscription in general. Whenever you write something like:
dispatcherTimer.Tick += dispatcherTimer_Tick;
You have to write also somewhere (usually in object cleanup):
dispatcherTimer.Tick -= dispatcherTimer_Tick;
Otherwise the event will still live. It is a really common error in C#, responsible for lots of memory leaks.
A quick workaround for you could be:
public void InitTimer()
{
if (dispatcherTimer != null)
{
dispatcherTimer.Tick -= dispatcherTimer_Tick;
}
dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += dispatcherTimer_Tick;
dispatcherTimer.Interval = new TimeSpan(0, Convert.ToInt32(textBox.Text), 0);
dispatcherTimer.Start();
}
Also if you can give me any suggestions about how I should improve my
code I'm listening
To be honest, this code is pretty bad, not testable and with bad names. To improve you craft I can suggest you to learn about the MVVM pattern and to read Clean Code.
Hope it helps.
What can I do in order to get rid of the old timer and let only the new one?
Try to stop the old timer before you start a new one:
private void btnRemind_Click(object sender, RoutedEventArgs e)
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (Window.GetWindow(this).Title == "ANM")
config.AppSettings.Settings["nIntervalDeTimpReminderANM"].Value = textBox.Text;
else if (Window.GetWindow(this).Title == "CAS")
config.AppSettings.Settings["nIntervalDeTimpReminderCAS"].Value = textBox.Text;
else if (Window.GetWindow(this).Title == "MS")
config.AppSettings.Settings["nIntervalDeTimpReminderMS"].Value = textBox.Text;
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
Window.GetWindow(this).Hide();
//STOP the old timer here:
if (dispatcherTimer != null)
{
dispatcherTimer.Stop();
}
InitTimer();
}
I'm new to C# WPF and I have a problem while running my program. My program freezes if my serial port (xbee on it) can't receive the required data in a specific time (Dispatcher).
So, I am trying to solve it by making a second window that will be actively waiting for a data to lessen the load of the main UI window. The problem I am experiencing is that I can't run the second window synchronously with my main window.
Any tips?
MAIN UI
public partial class Window5 : Window
{
SerialPort Senport = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
int flagger=0;
int fflagger=0;
DispatcherTimer timer1 = new DispatcherTimer(); //Feed Timer
DispatcherTimer timer2 = new DispatcherTimer();//Disabler Timer during Feeding
DispatcherTimer timer3 = new DispatcherTimer();//Disabler Timer during Drinking
DispatcherTimer timer4 = new DispatcherTimer();//Disabler Timer during Cleaning
DispatcherTimer timer5 = new DispatcherTimer();// Serial Port Data Receiver Timer
DispatcherTimer timer6 = new DispatcherTimer();//
DispatcherTimer timer7 = new DispatcherTimer();
public Window5()
{
InitializeComponent();
new Window2();
timer1.Interval = TimeSpan.FromSeconds(300);
timer2.Interval = TimeSpan.FromSeconds(15);
timer3.Interval = TimeSpan.FromSeconds(15);
timer4.Interval = TimeSpan.FromSeconds(60);
}
void timer_Tick(object sender, EventArgs e)
{
FEED.IsEnabled=true;
timer1.Stop();
}
void FEED_Click(object sender, RoutedEventArgs e)
{
fflagger=1;
flagger=1;
Sender();
timer1.Start();
timer2.Start();
Disabler();
MessageBox.Show("Feeds Dispensing is starting","Drinking Water Process",MessageBoxButton.OK,MessageBoxImage.Information);
timer1.Tick +=timer_Tick;
timer2.Tick +=Enabler;
// Xbee Code Will be Here
}
void FEED2_Click(object sender, RoutedEventArgs e)
{
flagger=2;
Sender();
timer3.Start();
Disabler();
MessageBox.Show("Water Dispensing is starting", "Drinking Water Process",MessageBoxButton.OK,MessageBoxImage.Information);
timer3.Tick +=Enabler;
// Xbee Code Will be Here
}
void Clean_Click(object sender, RoutedEventArgs e)
{
//Window4 w4 = new Window4();
flagger=3;
Sender();
timer4.Start();
Disabler();
MessageBox.Show("Cleaning Process is starting", "Cleaning Process",MessageBoxButton.OK,MessageBoxImage.Information);
//w4.Show();
timer4.Tick +=Enabler;
}
void CCTV_Click(object sender, RoutedEventArgs e)
{
Process.Start(#"C:\Program Files\ CMS 2.0\CMS");
}
public void Enabler(object sender, EventArgs e)
{
if(flagger==1)
{
FEED2.IsEnabled=true;
Clean.IsEnabled=true;
timer2.Stop();
}
else if(flagger==2 && fflagger==0)
{
FEED.IsEnabled=true;
FEED2.IsEnabled=true;
Clean.IsEnabled=true;
timer3.Stop();
}
else if(flagger==2 && fflagger==1)
{
FEED2.IsEnabled=true;
Clean.IsEnabled=true;
timer3.Stop();
}
else if(flagger==3 && fflagger==0)
{
FEED.IsEnabled=true;
FEED2.IsEnabled=true;
Clean.IsEnabled=true;
timer4.Stop();
}
else
{
FEED2.IsEnabled=true;
Clean.IsEnabled=true;
timer4.Stop();
}
}
// Function in disabling Buttons
public void Disabler()
{
if(flagger == 1)
{
FEED.IsEnabled=false;
FEED2.IsEnabled=false;
Clean.IsEnabled=false;
}
else if(flagger == 2)
{
Clean.IsEnabled=false;
FEED.IsEnabled=false;
FEED2.IsEnabled=false;
}
else
{
Clean.IsEnabled=false;
FEED.IsEnabled=false;
FEED2.IsEnabled=false;
}
}
//Function for Serial Port Sender
public void Sender()
{
if(flagger == 1)
{
try
{
if (!(Senport.IsOpen == true)) Senport.Open();
Senport.Write("AB");
}
catch {}
}
else if(flagger == 2)
{
try
{
if (!(Senport.IsOpen == true)) Senport.Open();
Senport.Write("BC");
}
catch {}
}
else if(flagger == 3)
{
try
{
if (!(Senport.IsOpen == true)) Senport.Open();
Senport.Write("CD");
}
catch {}
}
Senport.Close();
}
}
Window 2
public partial class Window2 : Window
{
SerialPort Senport = new SerialPort("COM4", 9600, Parity.None, 8,StopBits.One);
DispatcherTimer timer1 = new DispatcherTimer(); //Feed Timer
DispatcherTimer timer2 = new DispatcherTimer();//Disabler Timer during Feeding
DispatcherTimer timer3 = new DispatcherTimer();//Disabler Timer during Drinking
DispatcherTimer timer4 = new DispatcherTimer();//Disabler Timer during Cleaning
DispatcherTimer timer5 = new DispatcherTimer();// Serial Port Data Receiver Timer
DispatcherTimer timer6 = new DispatcherTimer();//
DispatcherTimer timer7 = new DispatcherTimer();
string rdata;
string rdata1;
public Window2()
{
InitializeComponent();
Window5 WORK1 = new Window5();
while(true)
{
if (!(Senport.IsOpen == true)) Senport.Open();
rdata= Senport.ReadLine();
rdata1.ToString();
rdata1 = rdata;
Senport.Close();
if(rdata1 == "FEED")
{
MessageBox.Show("Feeds already being dispense!", "Feeding Process",MessageBoxButton.OK,MessageBoxImage.Information);
}
if(rdata1 == "DRINK")
{
MessageBox.Show("Drinkable water is dispense!", "Drinking Water Process",MessageBoxButton.OK,MessageBoxImage.Information);
}
if(rdata1 == "CLEAN")
{
MessageBox.Show("Cleaning the cage is done!", "Cleaning Process",MessageBoxButton.OK,MessageBoxImage.Information);
}
}
}
}
Event based programming is largely superior to timer-based and blocking code. There are many levels of event based programming, from synchronous to asynchronous to full-fledged TPL. In your case, I would recommend starting by thoroughly reading the SerialPort documentation, and in particular the DataReceived event.
Adding your second UI is a large amount of unnecessary complexity.
Here's a basic example of how you can use SerialPorts with a state machine:
public class SerialPortTests
{
//Your states are pretty obscure to me, I'm making those up.
private enum States
{
State1,
State2,
State3
}
private States _state = States.State1;
private SerialPort _port = new SerialPort(/*Enter your port's config here*/);
public SerialPortTests()
{
_port.DataReceived += dataReceived; //This is the important line
_port.Open();
}
private void dataReceived(object sender, SerialDataReceivedEventArgs e)
{
var sendingPort = (SerialPort)sender;
var data = sendingPort.ReadExisting(); //Careful, you may have more than 1 line in data.
var dataLines = data.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
foreach (var line in dataLines)
{
verifyState(line);
processLine(line);
}
}
private void verifyState(string line)
{
//Your states are pretty obscure, I'm just making things up here.
if (line == "FEED" && _state != States.State1)
{
//Handle the error if you can, or just throw to learn more about the problem in the stack trace.
throw new ApplicationException("received FEED while in state " + _state);
}
}
private void processLine(string line)
{
if (line == "FEED")
{
//Don't use MessageBox unless you really have to. Change a label's text or something.
Console.WriteLine("Feeds already being dispense!");
_state = States.State2;
}
}
}
Essentially, the SerialPort class is capable of raising an event when it knows there is more data to read. You can subscribe to that event. In C#, that's called "handling" and it's done on this line:
_port.DataReceived += dataReceived; //This is the important line
This line means "everytime the port raises the DataReceived event, execute the private void dataReceived(...) function that I declared further down".
Your problem was that you used SerialPort.ReadLine() in a while(true) loop. That is almost always a bad idea. SerialPort.ReadLine() is a blocking call, as the documentation tells you. Your code will stop until it has read the NewLine characters from the COM port. If those characters don't come, your program will freeze forever. By using the "DataReceived" event, you are guaranteed that there is data to read, so even though I still call ReadExisting (which is also a blocking call) I already know that there will be data and that the line will execute and return very quickly. For most cases, it will be so quick that your UI will not freeze long enough for anyone to notice.
This is the lowest level event based programming. If you still see freezes, you have to use multi-threading, and that is very complex. Use it only if it's strictly necessary.
The rest of the code doesn't have anything to do with SerialPorts. It's there because you use timers to simulate a state machine, and that's also a bad idea. DataReceived will be fired when any data is received, regardless of the data, so it's important to keep track of your state to compare it with the incoming data. If you are expecting "FEED" (ie. your program is in State1, or StateFeed) and you receive "DRINK" then something went wrong and you have to do something about it. The least you can do when things go wrong is to throw an exception. Once you understand what went wrong, you can start adding code that handles exceptions gracefully.
so I am new to WPF and am just trying to make a simple little program. When you hit a start button it will continuosly print fake code until you hit a stop button. I have tried to make it repeat until the stop button is hit 10 different ways but none of them are working. The TextBlock element will update once (or never) and then the whole program becomes unusable and the loading cursor comes up. I would guess that instead of going through a cycle, and then updating the TextBlocks, it is doing everything in the background and not updating visually.
public partial class MainWindow : Window
{
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
Random r1 = new Random();
bool stop = false;
int numUse
public MainWindow()
{
InitializeComponent();
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
dispatcherTimer.Start();
}
//Executes when the start button is hit, begins timer
private void Button_Click(object sender, RoutedEventArgs e)
{
do
{
dispatcherTimer.Tick += dispatcherTimer_Tick;
} while (stop == false);
}
//Executes when the stop button is hit, ends timers do while loop
private void Button_Click_1(object sender, RoutedEventArgs e)
{
stop = true;
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
numUse = r1.Next(1, 2);
if (numUse == 1)
{
CodeBlock1.Text = "struct group_info init_groups = { .usage = ATOMIC_INIT(2) }; ";
CodeBlock2.Text = "";
CodeBlock3.Text = "struct group_info *groups_alloc(int gidsetsize){ ";
CodeBlock4.Text = "struct group_info *group_info; ";
CodeBlock5.Text = "int nblocks; ";
CodeBlock6.Text = "int i; ";
CodeBlock7.Text = "";
CodeBlock8.Text = "initialize stream";
}
else if (numUse == 2)
{
CodeBlock1.Text = "if (gidsetsize <= NGROUPS_SMALL) ";
CodeBlock2.Text = "group_info->blocks[0] = group_info->small_block; ";
CodeBlock3.Text = " else { ";
CodeBlock4.Text = " for (i = 0; i < nblocks; i++) { ";
CodeBlock5.Text = "b = (void *)__get_free_page(GFP_USER); ";
CodeBlock6.Text = " goto out_undo_partial_alloc; ";
CodeBlock7.Text = "} ";
CodeBlock8.Text = "";
} else
{
}
}
}
}
I have tried for loops, do while, using different methods in different orders. I understand that I likely messed up while going those routes so any method is ok for my purposes. Obviously I am using a Timer in this case.
It is not necessary to repeatedly call dispatcherTimer.Tick += dispatcherTimer_Tick in the while loop of Button_Click. I suspect that while this loop is running, nothing else on the message pump will run, including ticks from the DispatcherTimer.
You could probably do away with stop and merely act on the DispatcherTimer directly by calling Stop() from anywhere in the code.
Perhaps this instead:
public MainWindow()
{
InitializeComponent();
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
dispatcherTimer.Tick += dispatcherTimer_Tick; // set it up here
}
//Executes when the start button is hit, begins timer
private void Button_Click(object sender, RoutedEventArgs e)
{
dispatcherTimer.Start(); // start timer
}
//Executes when the stop button is hit, ends timers do while loop
private void Button_Click_1(object sender, RoutedEventArgs e)
{
dispatcherTimer.Stop(); // stop timer
}
I'm writing an app to listen music and watch video. In app, I have these 2 pages: 1 to play the audio playback agent (APA) - Page A, and one to play the video (using MediaElement) - Page B. While WP8 has an bug with the APA ( which I've asked here here (which I found a solution - stop the APA twice after and before when the MediaElement plays and closes).
Problem is, at the A page, I used an DispatcherTimer tick every second to check the APA instance positon, and when I leave this page, I have a funtion to stop this DispatcherTimer .
Even that, if I navigated to and from page A for a several times, and then navigate to page B, after 1 Second the app thrown an exception at the if (BackgroundAudioPlayer.Instance.PlayerState == .... It means that the DispatcherTimer still tick ????? How can I force to stop this :(
I posted all code which related to the DispatcherTimer here :
public DetailSongPage()
{
InitializeComponent();
this.DataContext = App.Model;
BackgroundAudioPlayer.Instance.PlayStateChanged += APA_Instance_PlayStateChanged;
}
DispatcherTimer timer = null;
private void APA_Instance_PlayStateChanged(object sender, EventArgs e)
{
if (BackgroundAudioPlayer.Instance.PlayerState == PlayState.Playing)
{
UpdateTracking();
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (BackgroundAudioPlayer.Instance.PlayerState == PlayState.Playing || BackgroundAudioPlayer.Instance.PlayerState == PlayState.Paused)
{
UpdateTracking();
}
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
timer.Stop();
timer.Tick -= timer_Tick;
timer = null;
}
private void UpdateTracking()
{
sldTracking.Maximum = BackgroundAudioPlayer.Instance.Track.Duration.TotalMilliseconds;
tbMaxTime.Text = string.Format(#"{0:mm\:ss}",BackgroundAudioPlayer.Instance.Track.Duration);
// ^ these 2 lines update the UI for the slider and textblock
if (timer == null)
{
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(1000);
timer.Tick += timer_Tick;
timer.Start();
}
}
private void timer_Tick(object sender, EventArgs e)
{
if (this.timer != null)
{
try
{
if (BackgroundAudioPlayer.Instance.PlayerState == PlayState.Playing || BackgroundAudioPlayer.Instance.PlayerState == PlayState.Paused)
{
sldTracking.Value = BackgroundAudioPlayer.Instance.Position.TotalMilliseconds;
tbCurrentTime.Text = string.Format(#"{0:mm\:ss}", BackgroundAudioPlayer.Instance.Position);
}
}
catch
{
return;
}
}
}
You could implement the IDispose in your class, in this implementation, stop the timer.
Then call the Dispose whenever you leave the page.
In the Dispose, you should write something like:
timer?.Stop();
I am having issues testing which icon my notifyIcon is using.
I have a notifyicon instantiated for my program. When the program runs I assign an icon to it in my code.
public Form1()
{
InitializeComponent();
notifyIcon1.Icon = Properties.Resources.LogoIcon;
}
I have 2 buttons, one which starts my timer, and 1 which stops my timer. The timer event is suppose to check which icon is currently being used and switch it to the other option, but it doesn't work using my test.
Timer miniClock = new Timer();
private void btnStartTimer_Click(object sender, EventArgs e)
{
miniClock.Interval = 1000;
miniClock.Tick += new EventHandler(MiniClockEventProcessor);
miniClock.Start();
}
private void MiniClockEventProcessor(Object myObject, EventArgs myEventArgs)
{
if (notifyIcon1.Icon == Properties.Resources.AlertIcon)
{
notifyIcon1.Icon = Properties.Resources.LogoIcon;
}
else
notifyIcon1.Icon = Properties.Resources.AlertIcon;
}
private void btnStopTimer_Click(object sender, EventArgs e)
{
miniClock.Stop();
btnTest.Enabled = true;
}
The frustrating part is when I start the timer, it will change the icon, but my test fails and it will only switch the icon in the else statement because there's no criteria to it except that it fails the if statement? How can I test which icon is currently being used, and then switch the icon to it's counterpart on the timer event call?
The reason is that every time you access an object directly from Properties.Resources, it actually reads it anew and creates a fresh object. Since == will test by reference and the references are not equal, your test fails each time.
The solution is to cache it, which you should be doing regardless for efficiency:
private static readonly Icon LogoIcon = Properties.Resources.LogoIcon;
private static readonly Icon AlertIcon = Properties.Resources.AlertIcon;
public Form1()
{
InitializeComponent();
notifyIcon1.Icon = LogoIcon;
}
and
Timer miniClock = new Timer();
private void btnStartTimer_Click(object sender, EventArgs e)
{
miniClock.Interval = 1000;
miniClock.Tick += new EventHandler(MiniClockEventProcessor);
miniClock.Start();
}
private void MiniClockEventProcessor(Object myObject, EventArgs myEventArgs)
{
if (notifyIcon1.Icon == AlertIcon)
{
notifyIcon1.Icon = LogoIcon;
}
else
notifyIcon1.Icon = AlertIcon;
}
private void btnStopTimer_Click(object sender, EventArgs e)
{
miniClock.Stop();
btnTest.Enabled = true;
}
I think it's easier to relay on some state then to Icon itself.
I imagine that yo setup AlertIcon or LogonIcon, based on some event, or on some changed state notification. It's better to have somewhere the simple bool statevariable that indicates what happens.
For example , to explain what am I talking about, is a pseudocode :
private void MiniClockEventProcessor(Object myObject, EventArgs myEventArgs)
{
if (!IsAlertState)
{
notifyIcon1.Icon = Properties.Resources.LogoIcon;
}
else
notifyIcon1.Icon = Properties.Resources.AlertIcon;
}
private bool IsAlertState {get;set}
On recived alert the property IsAlertState = true.
Something like this.