When observable created with Observable.FromEvent will be detached from event producer? - c#

UPDATE: found similar question: Rx - unsubscribing from events
Given the code:
interface IBitmapCapturer {
event EventHandler<EventArgs<RawBitmap>> Captured;
void Start();
void Stop();
}
public class Camera {
IBitmapCapturer m_capturer;
public RawBitmap CaptureBitmap() {
IObservable<IEvent<EventArgs<RawBitmap>>> observable = Observable.FromEvent<EventArgs<RawBitmap>>(
handler => m_capturer.Captured += handler,
handler => m_capturer.Captured -= handler);
m_capturer.Start();
IEvent<EventArgs<RawBitmap>> evn = observable.First();
m_capturer.Stop();
return evn.EventArgs.EventData;
}
}
What I'm doing here is capturing a shot from Camera but the only first one. IBitmapCapturer is some DirectShow-related stuff and doesn't provide a method to "make a shot", only generating events with bitmaps. So I'm using Reactive Extensions to take the first event and unsubscribe.
My doubts are about "observable.First()" line.
Do I understand correctly that after calling observable.First() my observable is detached from m_capturer (event producer)? If not then how can I make sure that there're no subscribers on m_capturer.Captured?

The framework ensures that the IDisposable value returned from Subscribe is disposed of when the sequence completes or errors, and the IDisposable returned by FromEvent unsubscribes from the event.
Since First is a blocking implementation of Take(1), the source sequence will be disposed after the first value is received (or after it throws an exception when the source is empty).
In short, you can be sure that the event handler is being removed after your call to First completes.

Related

What can cause this event to stop being invoked?

The Problem:
I am using asynchronous event handling in a class that invokes an event about 60 times per second. If I run the software for several hours I find that it eventually gets to a state where the event stops invoking the assigned delegate without seeing any exceptions or user input.
Here is the distilled version of the event code I am using:
class DataSource
{
public event EventHandler<DataReadyEventArgs> DataReady;
private void OnDataReady()
{
EventHandler<DataReadyEventArgs> evt = DataReady;
if (evt != null)
{
Trace.WriteLine("Invoking DataReady...");
DataReadyEventArgs args = new DataReadyEventArgs();
evt.BeginInvoke(this, args, new AsyncCallback(DataReadyHandled), null);
}
}
private void DataReadyHandled(IAsyncResult result)
{
AsyncResult aresult = result as AsyncResult;
EventHandler<DataReadyEventArgs> evt = aresult.AsyncDelegate as EventHandler<DataReadyEventArgs>;
if (evt != null)
{
try
{
evt.EndInvoke(result);
Trace.WriteLine("DataReady was handled.");
}
catch
{ }
}
}
}
class DataConsumer
{
public DataConsumer(DataSource src)
{
src.DataReady += HandleDataReady;
}
public void HandleDataReady(object sender, DataReadyEventArgs e)
{
Trace.WriteLine("Handling DataReady");
}
}
To avoid writing out further code to give the full picture, you can also make the following assumptions:
There is always a strong reference to the DataSource instance so it is not being garbage collected while the DataConsumer is expecting an event
The DataConsumer attaches its handler method once and does not remove it until the instance is garbage collected.
Here is the weird part; When I attach a debugger to the software in its broken state, I can see that the evt variable in OnDataReady() references an EventHandler instance and is not null. It actually calls BeginInvoke but the HandleDataReady method is never entered. The debugger shows that the EventHandler base class's Method property is null though. I can't seem to figure out how it is possible that the EventHandler is being changed.
The (First) Question:
What can cause the event in the above code to stop being invoked after several hours of runtime?
My Best Guess:
Could something completely unrelated in my application be corrupting the memory for the EventHandler? I am using both native and managed c++ libraries.
Update:
My best guess turns out to be unlikely, as I have run some other tests that make me reasonably sure the native libraries are not leaking or corrupting memory.
After reproducing the problem another time with logging, I can see that the event is not stopping entirely but being invoked on a ~19 hour interval! Obviously there is a long-running operation or blocking somewhere in the handler delegate.
To be certain that it's my code and not .NET, I have an updated question...
The (Second) Question:
Is there any behaviour built in to .NET (4.5) or its garbage collector that can block invocation of an EventHandler?

Is it possible to detect when EventHandlers are added and disposed of outside of process?

I think the answer is NO but I thought of asking to see if it's possible at all
Scenario: I have a WPF application that uses a class with static events to subscribe interactions between different controls
Basically,
public class EventNotifier
{
public static event EventHandler<SomeEventArgs> EventTriggered;
public static void NotifyEventTriggered(object source, SomeEventArgs eventArgs)
{
if (EventTriggered!= null)
{
EventTriggered(source, eventArgs);
}
}
}
Then from some controls some methods get subscribed:
EventNotifier.EventTriggered+= new EventHandler<SomeEventArgs>(SomeMethodToReceiveEvent);
And from some other controls the events are triggered:
EventNotifier.NotifyEventTriggered(null, eventArgs);
This is all very straightforward. When the controls that subscribed their methods are disposed the events are disposed as well:
EventNotifier.EventTriggered-= new EventHandler<SomeEventArgs>(SomeMethodToReceiveEvent);
Given the nature of WPF that makes memory leaks rife where events are not unsubscribed correctly, until now I've had to manually test every control every time a leak was happening to ensure events were being disposed correctly. This is very time consuming
Some tools that analyze memory usage that I've used are completely incompetent at identifying the event that wasn't unsubscribed that was causing a memory leak
This is why I've been dreaming of creating my own tool to detect every time a method is subscribed to an event and also detect every time it's unsubscribed
I know I could do it in code using properties like:
private static event EventHandler<SomeEventArgs> eventTriggered
public static event EventHandler<SomeEventArgs> EventTriggered
{
add
{
eventTriggered-= value;
eventTriggered+= value;
//Add code here to keep track somewhere of event
}
remove
{
eventTriggered-= value;
//Add code here to keep track somewhere of event
}
}
But my dream tool would be one that is external to my application and hooks up to a process to monitor its events. Am I just dreaming or is this possible in any way?

How do I make a function that does NOT run when a specific event is fired

Edit: For clarification, this is in Unity, and is tied to Update(). So the events will be triggered once per frame for any number of frames. Both events can be triggered independently by the user, but there is an overlap in which both can be triggered. In this case I only want one of the two methods that will be called by the two events to actually run.
I'm trying to make a method that is called by one event and other method that is called by a 2nd event be linked in a way that only one of those two methods can be called or ran at the same time.
The events are triggered by an action of the user, both events can be triggered at the same time. But I only want one of the two methods that would be called to actually run if both events are triggered.
I was thinking something along the like of the following example, obviously the example may not be accurate, but the gist of what I am trying to accomplish is there.
Pseudo Code Example:
public delegate void OneHandler();
public event OneHandler OneEvent;
private void One()
{
if(some requirement && TEvent != null)
{
TEvent();
}
}
public delegate void TwoHandler();
public event TwoHandler TwoEvent;
private void Two()
{
if(some requirement && TEvent != null)
{
TEvent();
}
}
SomeClass.OneEvent += ActionOne();
SomeClass.TwoEvent += ActionTwo();
private void ActionOne()
{
if(TwoEvent is not firing)
{
Do Something;
}
}
private void ActionTwo()
{
if(OneEvent is not firing)
{
Do Something;
}
}
A crude diagram. The tan area moves down/left, the green areas move diagonally. I essentially want the tan area which have their own events, to not run their methods if the mouse is within that entire area.
Events fire one at a time, not all at once. Even if the same user action was going to cause both events to fire one after the other, there is no way to know that both events will fire, or in what order they will fire.
To be more clear: I didn't mean events can never be fired concurrently. I mean that, in general, there is no piece of code that determines, for a particular situation, the complete set of events which will be fired. You can't tell ahead of time which will fire, or in which order, or even on which threads.
For example, a particular user interface action (or user gesture) might cause several events to fire. In general, you can't depend on the number of events to be fired, or the order in which they will be fired.
There are some situations, like in ASP.NET web forms, where you can be assured that if the user clicks a button which has a Click event handler, that the page Load event will fire and then that the button Click event will fire. But this is because this behavior is defined and documented that way. If the order changed, or if, for instance, the page Load event stopped firing, then this would break a large number of ASP.NET web forms applications.
If all you're trying to do is guarantee that concurrent triggering (like two threads running on different cores) will never be allowed, you'll want to use something like a mutex. You would have both handlers perform a WaitOne(0) to see if the other handler is working, returning immediately if the call returns false (since the other method must be executing) then in a guaranteed-execution block (such as a finally) you would release the mutex.
How about use bool variable as flag ?
private bool flag[2] = [false, false];
private void ActionOne()
{
flag[0] = true;
if(!(flag[0])&&flag[1]))
{
Do Something;
}
flag[0] = false;
}
private void ActionTwo()
{
flag[1] = true;
if(!(flag[0] && flag[1]))
{
Do Something;
}
flag[1] = false;
}

Is it necessary to deregister event handler?

I see this piece of code written by someone else:
public class DynamicPageContent : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context)
{
// it is necessary to
context.BeginRequest += new EventHandler(DynamicPageContent_BeginRequest);
}
//actual handler not pasting as it's meaningless for this question
}
As you can see the handler is registered but never deregistered. Wouldn't that create memory leak?
Event handling can create leaks but only under certain conditions.
The thing to watch out for is when the subscribing object has a larger lifespan than the publishing object.
The thing to watch out for is when the publishing object has a larger lifespan than the subscribing object.
In this case they appear to be the same object and then it is not necessary or useful to unsubscribe. That would only clutter your code.

C# Event handler Behavior

I have this code
List<DaSubscription> lstSubscription=new List<DaSubscription>();
for(int i=0;i<20;i++)//20 is just to simulate the behavior
{
DaSubscription Generic=new DaSubscription();
Generic.DataChanged += new DataChangedEventHandler(Generic_DataChanged);
lstSubscription.add(Generic);
}
//EVENT Handler which is raised from a 3rd party library [COM]
void Generic_DataChanged(DaSubscription aDaSubscription, DaItem[] items, ValueQT[] values, int[] results)
{
UpdateDataChangedDTO(items, values);
}
As the same event handler [m_daSubscription_Generic_DataChanged] is assigned to the multiple instance of same class [m_daSubscription]. Question i have is if at the same time multiple instances invokes this handler how will be handled here. will there will be any instance it shall overwrite the data. or the event handler will be separate for each instance.
The event handlers execute seperately. It sounds like your worried about the parameters being overwritten by another call to the handler. That won't happen (I don't think it is even possible). Since it doesn't look like you are accessing any shared objects in the event handler, you should be perfectly safe.

Categories

Resources