Can you access instance fields from RoleEnvironment.OnRoleChanging event handler? - c#

I'm trying to figure out how azure worker roles initiate RoleEnvironment events and how this affects field access.
With reference to my below code sample, my understanding is that:
The RoleEnvironmentChanging and RoleEnvironmentChanged event handlers will be run in the context of the thread that initiates the events
The event thread will be different than the thread being blocked by the AutoResetEvent
Does this mean that RoleEnvironmentChanged and OnStop will not be able to reference the instance field _someClass, would I have to make it static? Or do the event handlers have a closure around the instance variables?
Here is a simplified example:
public abstract class WorkerRole : RoleEntryPoint
{
private readonly AutoResetEvent _eventHandler = new AutoResetEvent(false);
private SomeClass _someClass;
public override bool OnStart()
{
RoleEnvironment.Changing += RoleEnvironmentChanging;
RoleEnvironment.Changed += RoleEnvironmentChanged;
_someClass = new SomeClass();
return base.OnStart();
}
public override void OnStop()
{
// Tell the other class to stop
_someClass.Stop();
base.OnStop();
}
public override void Run()
{
// Start some process in another class that executes on a different thread internally.
_someClass.Run()
_eventHandler.WaitOne(); // Wait, so the method doesn't return and the role restart.
base.Run();
}
private void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
{
e.Cancel = false // Never restart the role (just for this example)
}
void RoleEnvironmentChanged(object sender, RoleEnvironmentChangedEventArgs e)
{
_SomeClass.Refresh() // Just proving I can call this variable from here.
}
}

Your 2 statements are correct (the event handler running on a different thread than your Run() method), but that doesn't have anything to do with accessing the member variables of your WorkerRole class. The code in the event handlers are instance methods, not static methods, so they are able to access the members of the class.

Related

How to use event handler with delegate from child class with interface

I've done some searching here and haven't been able to get a clear answer to my problem.
I have a several child classes all with 1 interface. I have a parent class that contains a variable and this variable is created as a new instances of one of those child classes depending on external params. Here's some code:
public interface I
{
public delegate void ExecutionCompletedHandler(bool status);
public event ExecutionCompletedHandler executionCompleted;
public void Execute();
}
public class C1 : I
{
public void Execute()
{
// Create background worker and execute DoStuff
}
public void BackgroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
bool status = (bool)e.Result;
this.executionCompleted(true);
}
}
public class C2 : I
{
// Same setup as C1
}
public class C3 : I
{
// Same setup as C1
}
public class MyManager
{
public void doStuff(int val)
{
var compObj = null;
// compObj is now instantiated as new instance of C1, C2 or C3 depending on val
// ex: compObj = new C1();
compObj.executionCompleted += new I.ExecutionCompletedHandler(executionCompletedHandler);
compObj.Execute();
}
private void executionCompletedHandler(bool status)
{
// Do stuff with status and exit gracefully
}
}
This is what I'd like to do but I know it's not right. I feel as if I'm 90% of the way there. It's saying that the executionCompleted variable in the C1 class is hiding the interface's variable. I've tried to follow various guides and examples but haven't been able to figure this out. Thanks!
Edit: I'm using .NET 4.0 in Visual Studio 2010.
EDIT 2:
I was able to figure it out with help from #NikProtsman...I converted the interface to an abstract class, and in that abstract class, implemented a CompleteExecution function. In this function, I would call the event handler. In the C1/C2/C3 classes, when background worker is finished executing, I would call this method. Works perfectly. We're in the process of upgrading to VS 2019 and after this, I'm going to push to make that happen quicker! Thanks!
Try this:
In your interface, change Execute to:
public Task Execute();
In your Class C1:
//Add this line to conform to Interface
public event I.ExecutionCompleteHandler executionCompleted;
public async Task Execute()
{
// Create background worker and execute DoStuff
await DoStuff();
// You'll need to supply appropriate args here
BackgroundWorkerCompleted(this, args);
}
public void BackgroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
bool status = (bool)e.Result;
//Changed this line, assumed you needed the status from the line above
executionCompleted?.invoke(status);
}
Next your MyManager should look like this:
public class MyManager
{
public async Task doStuff(int val)
{
var compObj = null
// compObj is now instantiated as new instance of C1, C2 or C3 depending on val
compObj = new C1();
// Subscribe to the 'executioncompleted' event in your new instance
compObj.executionCompleted += HandleExecutionComplete;
// Execute your code
await compObj.Execute();
// Unsubscribe from the event (cleaning up after yourself)
compObj.executionCompleted -= HandleExecutionComplete;
}
private void HandleExecutionComplete(bool status)
{
// Do stuff with status and exit gracefully
}
}
The key point here is assigning the Execution Handler properly in your Manager, and then using it to subscribe to the C1 class event. Inside the C1 class, use a Task for DoStuff, and await it in Execute which becomes an async Task. Once DoStuff is done, the WorkerCompleted task runs, executes your handler, and off you go.
This can all be simplified somewhat but that is outside the scope of this question. The idea is how the control flow will work and using async calls with await to make sure your program waits for what it needs, and then continues, and how you subscribe to that event externally.
Just be sure to await your MyManager.doStuff call on the outside as well, otherwise any results you are waiting for will not get picked up in time.

Worker raising a static event so that consumers can subscribe to it without holding the same instance to the worker

I have a non-static class which does something and when it finishes it, I want to raise an event in my system.
Is it OK if I do something like:
public class Worker
{
public void DoWork()
{
SystemEvents.RaiseWorkDoneEvent(this, ...);
}
}
public static class SystemEvents
{
public delegate void WorkDoneEventHandler(object sender, EventArgs e);
public static event WorkDoneEventHandler WorkDoneEvent;
public void RaiseWorkDoneEvent(...)
{
WorkDoneEvent(...)
}
}
public class Consumer
{
// subscribe to SystemEvents.WorkDoneEvent
// This class has no instance (or not the same instance) of Worker when it fires the event.
}
I understand the event belongs to Worker, however, I won't have an instance of it in my Consumer when this event happens.
Is this approach OK?

Will several bindings of static/global Event handler to Events in a class, lead to a thread/memory leak?

I have a class with EventHandler bindings at the constructor, that will be instantiated thousand times within application lifecycle. The question is: Will this approach leads to memory/thread leaks?
I did this way (code below), because I need to be notified every time SomeMethod() runs, whatever instance run it. Foo class (the publisher) will be short-lived, however the handlers will live until the application closes.
I ask this because, when working with Windows Forms, each form can hold several event handlers/delegates and everything is fine because all those delegates are inside the form and will be disposed when the form closes. But how about static event handlers/delegates, that could be even on separate projects?
Will I need to write a destructor to detach those event handlers?
Should I go with Weak Event Pattern?
Restriction: I must do this with .NET 3.5. I know I could do this with TPL, setting a "Fire and Forget" Task.
Thank you in advance.
Code:
public class Foo
{
public event EventHandler SomeEvent;
public Foo()
{
SomeEvent += FooHandlers.Foo_SomeEvent1;
SomeEvent += FooHandlers.Foo_SomeEvent2;
}
public void RaiseEvents(EventHandler evt, EventArgs args)
{
var eventObj = evt;
var listeners = eventObj.GetInvocationList();
foreach (var listener in listeners)
{
var method = (EventHandler)listener;
ThreadPool.QueueUserWorkItem(callBack => method(this, args));
// Handlers will do a lot of things, so I don't want
// them blocking the Main thread
}
}
public void SomeMethod()
{
// do something here
RaiseEvents(SomeEvent, new EventArgs());
}
}
public static class FooHandlers
{
public static void Foo_SomeEvent1(object sender, EventArgs e)
{
//do something here
}
public static void Foo_SomeEvent2(object sender, EventArgs e)
{
//do something different here
}
}
Since your handlers are static methods the delegate you're adding to the event doesn't have an object instance, so there is no object instance being kept alive for the duration of the object with the event.
And even if you did use an object instance to attach the handler, it wouldn't be a problem, because the object with the event is short lived. The only time there is a problem is when the object with the event is long lived, and the object that has a handler to itself assigned is short lived, and consumes a lot of resources to keep alive.

Creating a thread to handle events for a particular class

I have a WPF application and I need to listen to, and handle events for the lifetime of the application for a certain class.
Is it bad practice to create a wrapper class, create a static instance of it and call "StartListening()"? What if an unhanded exception happens on this static instance? Will it tear down the entire application as it would in an ASP.NET application?
Should I QueueUserWorkItem, create the class, attach events, and then put some kind of while(true){} statement to keep the thread alive?
What is the best practice?
To me this seems like a classic publisher/listener problem.
I would create an interface: IMyClassNameEventListener and make MyClass take an instance of it as a constructor parameter. Then in the constructor I would call the Attach(MyClass obj) method on the interface instance. Of course, the listener would have a singleton lifecycle, it doesn't need to be static.
A slightly better approach would be to use a factory to create instances of MyClass which would then do the attaching, so the Attach call and the dependency are out of the constructor.
Wether the app would fail would be dependent on how you start the listener. You can look into the TaskFactory class, it provides options to handle exception propagation. How would you want the app to behave if the listener fails?
Of course in the listener object itself, you only need to have code run when there is something to handle. So, when you receive an event, you startup a thread. You can use a queue of actions if you'd want to have only one thread running.
Inside the listener class, you might want to have something like the following:
private Queue<Action> ActionQueue = new Queue<Action>();
private object LockObj = new Object();
private volatile bool IsRunning;
public void Attach(Class1 obj)
{
obj.SomeEvent += this.HandleEvent;
}
private void HandleEvent(object sender, EventArgs e)
{
lock(this.LockObj)
{
this.ActionQueue.Enque(() => this.Handle(sender, e));
if (!this.IsRunning)
{
Task.Factory.StartNew(() => this.Loop() );
}
}
}
private void Loop()
{
this.IsRunning = true;
while ((Action action = this.DequeueAction()) != null)
action();
this.IsRunning = false;
}
private Action DequeueAction()
{
lock (this.LockObj)
{
return this.ActionQueue.Count > 0 ? this.ActionQueue.Dequeue() : null;
}
}
private void Handle(object sender, EventArgs e)
{
//handling code
}

Calling Invoke/BeginInvoke from a thread

I have a C# 2.0 application with a form that uses a class that contains a thread.
In the thread function, rather than call the event handler directly, it is invoked. The effect is that the owning form does not need to call InvokeRequired/BeginInvoke to update its controls.
public class Foo
{
private Control owner_;
Thread thread_;
public event EventHandler<EventArgs> FooEvent;
public Foo(Control owner)
{
owner_ = owner;
thread_ = new Thread(FooThread);
thread_.Start();
}
private void FooThread()
{
Thread.Sleep(1000);
for (;;)
{
// Invoke performed in the thread
owner_.Invoke((EventHandler<EventArgs>)InternalFooEvent,
new object[] { this, new EventArgs() });
Thread.Sleep(10);
}
}
private void InternalFooEvent(object sender, EventArgs e)
{
EventHandler<EventArgs> evt = FooEvent;
if (evt != null)
evt(sender, e);
}
}
public partial class Form1 : Form
{
private Foo foo_;
public Form1()
{
InitializeComponent();
foo_ = new Foo(this);
foo_.FooEvent += OnFooEvent;
}
private void OnFooEvent(object sender, EventArgs e)
{
// does not need to call InvokeRequired/BeginInvoke()
label_.Text = "hello";
}
}
This is obviously contrary to the method used by Microsoft APIs that use background threads like System.Timers.Timer and System.Io.Ports.SerialPort. Is there anything inherently wrong with this method? Is it dangerous in some way?
Thanks,
PaulH
Edit: also, what if the form did not subscribe to the event right away? Would it clog the Form's message queue with events the form wasn't interested in?
This is a threadsafe call, the method will be processed in the thread of the form.
Nothing wrong with it when looking at it from a conceptual perspective.
Timers are more elegant for such tasks, though. However, it could be that a timer with an interval of 10ms slows down the GUI, that's probably why Invoke was used.
You do not need a call to InvokeRequired, since it is clear that the Control is in an other thread. Also, BeginInvoke only needs to be called when you want to call a method asynchronously, which obviously isn't the case here.
Regarding your edit:
No, the message queue will not be clogged. No event will be fired if no handler has been registered. Take another look at your code ;)

Categories