How do I make sure no handlers are attached to an event? - c#

I am adding an event handler like this:
theImage.MouseMove += new MouseEventHandler(theImage_MouseMove);
but in my application, this code gets run every time the page is shown, so I want to attach the event handler only once, but how can I tell if a handler has been set yet or not, something like this:
if(theImage.MouseMove == null) //error
theImage.MouseMove += new MouseEventHandler(theImage_MouseMove);

I might me missing something, but if you just want to make sure that the handle is only called once, why don't you use -= before adding it. Something like this:
public static void Main(string[] args)
{
var timer = new Timer(1000);
timer.Elapsed -= new ElapsedEventHandler(timer_Elapsed);
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Elapsed -= new ElapsedEventHandler(timer_Elapsed);
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();
System.Threading.Thread.Sleep(4000);
}
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Hit!");
}
The handler will only run once every second.

You can shorten it down if you only want to attach once:
theImage.MouseMove -= theImage_MouseMove; //If it wasn't attached, doesn't matter
theImage.MouseMove += theImage_MouseMove;

I'm not sure if this is the best solution, but the way I usually do this is to simply use an unsubscribe before the subscribe.
If you do something like:
TheImage.MouseMove -= new MouseEventHandler(theImage_MouseMove);
TheImage.MouseMove += new MouseEventHandler(theImage_MouseMove);
It will only ever get added once. If it doesn't already exist (the first time it's triggered), the -= doesn't hurt anything if it hasn't been subscribed to previously.

theImage.MouseMove.GetInvocationList().Length

Related

C# Timer.Elapsed Event firing twice consecutively

I have an application that calls static methods in a DLL every 60 seconds as part of a system "self-check" application. When I manually run the methods, they all complete in less than 10 seconds. My problem is the timer.elapsed event is firing twice, one right after the other. To add to that, for each time the timer elapses, the event fires one more time. (e.g. first time it's 2 firings, second it's 3, third it's 4, etc.) I have tried setting the timer.AutoReset = false along with setting timer.Enabled = false at the beginning of the elapsed event and then setting it to true at the end of the event. I've tried resetting the interval in the event. Every post I have found indicates that the above actions should have resolved this problem. Can anyone help me find what I'm missing?
static Timer cycle = new Timer();
static int cycCount = 0;
static void Main(string[] args)
{
Console.WriteLine("Firebird Survivor Auto Cycle Started.");
Console.CancelKeyPress += Console_CancelKeyPress;
cycle.Interval = 60000; //set interval for service checks.
cycle.Elapsed += new ElapsedEventHandler(CycleComplete_Elapsed);
cycle.AutoReset = false;
cycle.Enabled = true;
cycle.Elapsed += CycleComplete_Elapsed;
while (1 == 1) //stop main method from completing indefinitely
{
//WAIT FOR TIMER TO ELAPSE
}
}
private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
cycle = null;
}
static void CycleComplete_Elapsed(object sender, ElapsedEventArgs e) //method triggered by timer
{
cycle.Enabled = false;
cycCount++;
WormholeServiceControls.CheckWormHoleStatus();
TimeControls.CheckTimePl(); //call time check
PegasusServiceControls.CheckPegasusStatus(null);
Console.Clear();
Console.WriteLine("--------------------------");
Console.WriteLine(String.Format("| Successful Cycles: {0} |", cycCount));
Console.WriteLine("--------------------------");
cycle.Enabled = true;
}
It seems your problem comes from the event handling you are doing. You are assigning the Elapsed event more than one time:
cycle.Elapsed += new ElapsedEventHandler(CycleComplete_Elapsed);
cycle.Elapsed += CycleComplete_Elapsed;
Why this two lines?. You will be all right with only this:
cycle.Elapsed += new ElapsedEventHandler(CycleComplete_Elapsed);

C# -= operator to unsubscribe from a single event multiple times

In C# 5, what is the behavior of the -= operator when unsubscribing from events.
Assume subscribing to the same event multiple times is valid for this application logic, such as follows:
Property_Saved += Property_Saved_Handler;
Property_Saved += Property_Saved_Handler;
Property_Saved += Property_Saved_Handler;
Now we are subscribed three times.
After unsubscribing with the following one line of code:
Property_Saved -= Property_Saved_Handler;
How many subscriptions are left? 2? none? ...?
Two are left after that. Each -= only removes one subscription. At least, that's the case if it's using just a regular delegate to back the event.
You can see this easily without really involving events:
using System;
public class Program
{
public static void Main(string[] args)
{
Action action = () => Console.WriteLine("Foo");
// This is a stand-in for the event.
Action x = null;
x += action;
x += action;
x += action;
x -= action;
x(); // Prints Foo twice
}
}
Strictly speaking, an event subscription could do anything. You could implement an event like this:
private EventHandler weirdEvent;
public event EventHandler WeirdEvent
{
add { weirdEvent += value; } // Subscribe as normal
remove { weirdEvent = null; } // I'm bored with *all* the handlers
}
But normally events just delegate to Delegate.Combine and Delegate.Remove, which are the methods that += and -= are syntactic sugar for in C#.
My article on events and delegates contains more details about exactly what happens with combination and removal.
private void button1_Click(object sender, EventArgs e)
{
// set breakpoint
}
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button1.Click -= new System.EventHandler(this.button1_Click);
Invoking the click event will show the breakpoint hit twice.
This should be also safe.
Property_Saved += Property_Saved_Handler;
Property_Saved -= Property_Saved_Handler;
Property_Saved -= Property_Saved_Handler;
Just make your own test using GetInvocationList
public delegate void MyEventHandler(string s);
public event MyEventHandler MyEvent;
MyEventHandler #event = s => { };
MyEvent += #event;
Console.WriteLine(MyEvent.GetInvocationList().Length);
MyEvent += #event;
Console.WriteLine(MyEvent.GetInvocationList().Length);
MyEvent -= #event;
Console.WriteLine(MyEvent.GetInvocationList().Length);
This will print
1
2
1

Windows Service Timer Not Firing

I have a windows service whose timer doesn't want to fire. I have an attached debugger but it gave me no useful information. The odd thing is; that this service is nearly identical to another service I built which works as intended.
The code in question is this:
public Constructor()
{
_timer.Interval += 300000;
InitializeComponent();
_timer.Enabled = true;
//_timer.Start(); <this is not actually here. just one of the things i tried
_timer.Elapsed += new ElapsedEventHandler(timer_Tick);
}
After which I have:
private void timer_Tick(object sender, EventArgs e)
{
DoWorkHere();
}
I dont understand why attaching the "ElapsedEventHandler" doesn't fire the timer_Tick method.
Edit: "_timer" is:
System.Timers.Timer _timer = new System.Timers.Timer();
Problem was with permissions.
Sorry for wasting anyone's time.

How to delay Silverlight's loading screen?

I have an experimental project in silverlight, that has no database and scarce resources. Now, I wanted to know if you can prolong or delay the Silverlight loading screen, so I can check what I have modified in the loading page. Problem is, it loads too fast for me to check. I have no data to fetch from the webservice or any resources needed. I'm just experimenting in modifying Silverlight's load page. Can this be done code-wise? Any help would be appreciated. Thanks.
Already found the answer. I just needed a timer for things. thanks for all the queries, anyway
private void Application_Startup(object sender, StartupEventArgs e)
{
var timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(10);
EventHandler eh = null;
eh = (s, args) =>
{
timer.Stop();
this.RootVisual = new Test();
timer.Tick -= eh;
};
timer.Tick += eh;
timer.Start();
}

Stopping DispatcherTimer in its own anonymous Tick event handler

Is it safe to do something like this:
private void MyFunction()
{
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 1);
timer.Tick += (object sender, object e) =>
{
timer.Stop();
// Some code here
};
timer.Start();
}
Matt raise the point that the way you attach the anonymous method that there is no easy way to detach it. Here is a general pattern you can use to enable you to detach if necessary.
private void MyFunction()
{
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 1);
EventHandler eh = null;
eh = (object sender, object e) =>
{
timer.Tick -= eh;
timer.Stop();
// Some code here
};
timer.Tick += eh;
timer.Start();
}
However in this specific case there is nothing wrong with the way your original code works since the timer becomes collectable as soon as it is stopped.
Yes. Your timer will fire once.
Edit: I'll rephrase my answer based on the comments. In the situation you've given, yes it's perfectly safe to use an anonymous delegate.
There are some situations in which adding an anonymous delegate and not detaching it could prevent your class from being garbage collected (for example, attaching an anonymous delegate to a singleton). See this answer for information about when it is and isn't necessary to detach the event handler.

Categories

Resources