Async event handler callback through event arguments - c#

I have a problem when I need to collect event argument data that has been changed through event hadnler that contains async calls. As you can see in code below, MessageReceiver raises event and collects data from property "Change", and continues processing. Problem is when event handler is async because it calles asny method with "await". In method OnMyEvent code continues immediately after calling the handler, it does not wait for handler to finish, so "Change" property is not set... How to make things more "in sync"?
public class MyEventArgs:EventArgs
{
public bool Change { get; set; }
}
public delegate void MyEventHandler(object sender, MyEventArgs e);
public class MessageReceiver
{
public event MyEventHandler MyEvent;
public void RaiseEvent()
{
OnMyEvent();
}
protected void OnMyEvent()
{
MyEventArgs e = new MyEventArgs();
if (MyEvent != null)
MyEvent(this, e);
if (e.Change)
Console.WriteLine("Change occured");
}
}
public class Form
{
MessageReceiver mr;
public Form(MessageReceiver MR)
{
mr = MR;
mr.MyEvent += Mr_MyEvent;
}
private async void Mr_MyEvent(object sender, MyEventArgs e)
{
string s = await GetString();
e.Change = true;
}
public async Task<string> GetString()
{
return await Task.Factory.StartNew(() =>
{
return Guid.NewGuid().ToString();
}
);
}
}
public class Program
{
static void Main(string[] args)
{
MessageReceiver mr = new MessageReceiver();
Form frm = new Form(mr);
mr.RaiseEvent();
}
}

I discuss a variety of approaches for asynchronous events on my blog. I recommend the deferral approach, which you can implement using the DeferralManager and IDeferralSource types from my Nito.AsyncEx.Coordination library:
public class MyEventArgs: EventArgs, IDeferralSource
{
private readonly DeferralManager _deferralManager;
public MyEventArgs(DeferralManager deferralManager)
{
_deferralManager = deferralManager;
}
public bool Change { get; set; }
public IDisposable GetDeferral() { return _deferralManager.GetDeferral(); }
}
public class MessageReceiver
{
protected async Task OnMyEventAsync()
{
if (MyEvent != null)
{
DeferralManager deferralManager = new DeferralManager();
MyEventArgs e = new MyEventArgs(deferralManager);
MyEvent(this, e);
await deferralManager.WaitForDeferralsAsync();
}
if (e.Change)
Console.WriteLine("Change occured");
}
}
public class Form
{
private async void Mr_MyEvent(object sender, MyEventArgs e)
{
using (e.GetDeferral())
{
string s = await GetString();
e.Change = true;
}
}
}

Related

Assign event and function in extension method as argument

I have a list of objects and I want to assign values in a factory method. I have checked similar questions but they have access to a method in existing assembly. I want to use a custom method and also define which event should be set.
for example
mylist.Assign(nameofevent,assignfuntion);
the usage something like
public static void Assign(this Control[] controls,eventhandler #event,Action func)
{
foreach (var item in controls)
//assign function to event
item.clicked += func;//Preferably clicked must be Specified from argument
}
Trying to help to get to the bottom of what is wrong with Shervin Ivari's question. I'm illustration how you can achieve it. But still unsure if this is what you want?
public static void Main()
{
var listeners = new List<SomeClassWithListener>
{
new SomeClassWithListener(),
new SomeClassWithListener(),
new SomeClassWithListener()
};
var theEvent = new SomeClassWithEvent();
MatchEmUp(listeners, theEvent);
theEvent.RaiseEvent();
}
public static void MatchEmUp(IEnumerable<SomeClassWithListener> listeners, SomeClassWithEvent theEvent)
{
foreach(SomeClassWithListener listener in listeners)
theEvent.ItsAlive += listener.ThenIllSlayIt;
}
public class SomeClassWithListener
{
public void ThenIllSlayIt(object sender, EventArgs e)
{
Console.WriteLine("Chaaaaaarge!");
}
}
public class SomeClassWithEvent
{
public EventHandler ItsAlive;
public void RaiseEvent()
{
ItsAlive.Invoke(this, new EventArgs());
}
}
https://dotnetfiddle.net/4Y13cf
Or by using delegates, EventHandler is also a delegate:
public static void Main()
{
var listener1 = new SomeClassWithListener();
var listener2 = new SomeClassWithListener();
var listener3 = new SomeClassWithListener();
var listeners = new List<EventHandler>
{
listener1.ThenIllSlayIt,
listener2.ThenIllSlayIt,
listener3.ThenIllSlayIt
};
var theEvent = new SomeClassWithEvent();
MatchEmUp(listeners, theEvent);
theEvent.RaiseEvent();
}
public static void MatchEmUp(IEnumerable<EventHandler> listeners, SomeClassWithEvent theEvent)
{
foreach(EventHandler listener in listeners)
theEvent.ItsAlive += listener;
}
public class SomeClassWithListener
{
public void ThenIllSlayIt(object sender, EventArgs e)
{
Console.WriteLine("Chaaaaaarge!");
}
}
public class SomeClassWithEvent
{
public EventHandler ItsAlive;
public void RaiseEvent()
{
ItsAlive.Invoke(this, new EventArgs());
}
}
https://dotnetfiddle.net/k16lsy

Pass event through classes C#

I have a first class that raises an event when some changes occur:
public class MyFirstClass {
public event EventHandler ChangesHappened;
public MyFirstClass() {
}
public void MyMethod() {
//Thing happened
ChangesHappened?.Invoke(this, new EventArgs());
}
}
I also have a second class that have a list of FirstClass:
public class MySecondClass {
private List<MyFirstClass> first;
public MySecondClass() {
foreach(var f in first) {
first.Changed += (s, e) => {};
}
}
}
And last I have a WPF application with an instance of SecondClass. How can I handle the Changed event (FirstClass) from WPF? Should I create an event in SecondClass and raise it inside first.Changed += (s, e) => { NewEvent(this, new EventArgs()); } and then catch this in the WPF?
The objective is get the Changed event in the WPF application.
It seems to me that this is the simplest answer:
public class MySecondClass
{
public event EventHandler ChangesHappened;
private List<MyFirstClass> first;
public MySecondClass()
{
foreach (var f in first)
{
f.ChangesHappened += (s, e) => ChangesHappened?.Invoke(s, e);
}
}
}
Another option is to use Microsoft's Reactive Framework which lets you pass events (well observables) around as first-class language citizens.
You could do this:
void Main()
{
var msc = new MySecondClass();
msc.Changes.Subscribe(ep =>
{
/* Do stuff with
ep.Sender
ep.EventArgs
from the `MyFirstClass` instances
*/
});
}
public class MyFirstClass
{
public event EventHandler ChangesHappened;
public IObservable<EventPattern<EventArgs>> Changes;
public MyFirstClass()
{
this.Changes = Observable.FromEventPattern<EventHandler, EventArgs>(
h => this.ChangesHappened += h, h => this.ChangesHappened += h);
}
public void MyMethod()
{
ChangesHappened?.Invoke(this, new EventArgs());
}
}
public class MySecondClass
{
public IObservable<EventPattern<EventArgs>> Changes;
private List<MyFirstClass> first = new List<MyFirstClass>();
public MySecondClass()
{
this.Changes = first.Select(f => f.Changes).Merge();
}
}
As #Enigmativity already mentioned: When you have a class, that has to manage other classes (bunch of MyFirstClass references) then you have to forward your events from sub class to manager class.
public class MySecondClass
{
public event EventHandler Changed;
private List<MyFirstClass> firstClassList;
public MySecondClass()
{
firstClassList = new List<MyFirstClass>();
}
public void AddMyFirstClassList(List<MyFirstClass> firstClassList)
{
foreach (var firstClass in firstClassList)
AddMyFirstClass(firstClass);
}
public void AddMyFirstClass(MyFirstClass firstClass)
{
// from sub class to manager class
firstClass.Changed += firstClass_Changed;
firstClassList.Add(firstClass);
}
private void firstClass_Changed(object sender, EventArgs args)
{
Changed?.Invoke(sender, args);
}
public void RemoveMyFirstClass(MyFirstClass firstClass)
{
MyFirstClass.Remove -= firstClass_Changed;
firstClassList.Remove(firstClass);
}
}
Another option is to pass a callback function. You should avoid this, unless you need it explicity:
public class MyFirstClass
{
EventHandler handler;
public MyFirstClass(EventHandler handler)
{
this.handler = handler;
}
public void MyMethod()
{
handler?.Invoke(this, new EventArgs());
}
}
public class MySecondClass
{
private List<MyFirstClass> firstClassList;
public MySecondClass()
{
firstClassList = new List<MyFirstClass>();
}
// you have instantiated your class and passed your callback function previously.
public void AddMyFirstClass(MyFirstClass firstClass)
{
firstClassList.Add(firstClass);
}
// for demonstrating the instantiation.
public void AddMyFirstClass(EventHandler handler)
{
firstClassList.Add(new MyFirstClass(handler));
}
}

C# Custom event not working

public delegate void MessageReceiveEventHandler(MessageReceiveEventArgs e);
public event MessageReceiveEventHandler MessageReceiveEvent;
public class MessageReceiveEventArgs : EventArgs
{
public string Message { get; }
public MessageReceiveEventArgs(string Message)
{
this.Message = Message;
}
}
private void OnMessageReceiveEvent(string Message)
{
if (MessageReceiveEvent == null) return;
MessageReceiveEventArgs MessageREvent = new MessageReceiveEventArgs(Message);
MessageReceiveEvent(MessageREvent);
}
This is my event code. and i call event when my socket client receive message(data). but event not worked..
ClientSocket cs;
public Form1()
{
InitializeComponent();
cs = new ClientSocket();
cs.MessageReceiveEvent += Cs_MessageReceiveEvent1;
}
private void Cs_MessageReceiveEvent1(ClientSocket.MessageReceiveEventArgs e)
{
listBox1.Items.Add(e.Message);
}
I tried this.
I cannot see anywhere where you are raising the event. Try making the OnMessageReceiveEvent method public and then call it from the Form1 constructor.
public Form1()
{
InitializeComponent();
cs = new ClientSocket();
cs.MessageReceiveEvent += Cs_MessageReceiveEvent1;
cs.OnMessageReceiveEvent("Testing Event");
}

Firing custom event in the UI thread

The example below functions fine, but I want to have the Complete event fire its event handlers in the UI thread. I don't want HasCompleted() to have to worry about checking if it's on the UI thread or not. Calls to HasCompleted() should always be invoked on the UI thread. How do I do this?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var game = new Game();
game.Complete += HasCompleted;
game.Load();
}
private void HasCompleted()
{
if (label1.InvokeRequired)
{
label1.BeginInvoke(new Action(() => label1.Text = "complete"));
}
else
{
label1.Text = "complete";
}
}
}
public class Game
{
public Game()
{
}
public event MethodInvoker Complete;
public void Load()
{
var task = new Task(new Action(() =>
{
Thread.Sleep(500);
OnComplete();
}));
task.Start();
}
private void OnComplete()
{
if (Complete != null)
{
Complete();
}
}
}
Capture the current synchronization context when you create the Game object and use that to marshal the event to the context that was current when the object was first created:
public class Game
{
private SynchronizationContext context;
public Game()
{
context = SynchronizationContext.Current ??
new SynchronizationContext();
}
public MethodInvoker Complete;
public void Load()
{
//...
}
private void OnComplete()
{
if (Complete != null)
{
context.Post(_ => Complete(), null);
}
}
}

Super-simple example of C# observer/observable with delegates

I recently started digging into C# but I can't by my life figure out how delegates work when implementing the observer/observable pattern in the language.
Could someone give me a super-simple example of how it is done? I have googled this, but all of the examples I found were either too problem-specific or too "bloated".
The observer pattern is usually implemented with events.
Here's an example:
using System;
class Observable
{
public event EventHandler SomethingHappened;
public void DoSomething() =>
SomethingHappened?.Invoke(this, EventArgs.Empty);
}
class Observer
{
public void HandleEvent(object sender, EventArgs args)
{
Console.WriteLine("Something happened to " + sender);
}
}
class Test
{
static void Main()
{
Observable observable = new Observable();
Observer observer = new Observer();
observable.SomethingHappened += observer.HandleEvent;
observable.DoSomething();
}
}
See the linked article for a lot more detail.
Note that the above example uses C# 6 null-conditional operator to implement DoSomething safely to handle cases where SomethingHappened has not been subscribed to, and is therefore null. If you're using an older version of C#, you'd need code like this:
public void DoSomething()
{
var handler = SomethingHappened;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
In this model, you have publishers who will do some logic and publish an "event."
Publishers will then send out their event only to subscribers who have subscribed to receive the specific event.
In C#, any object can publish a set of events to which other applications can subscribe.
When the publishing class raises an event, all the subscribed applications are notified.
The following figure shows this mechanism.
Simplest Example possible on Events and Delegates in C#:
code is self explanatory, Also I've added the comments to clear out the code.
using System;
public class Publisher //main publisher class which will invoke methods of all subscriber classes
{
public delegate void TickHandler(Publisher m, EventArgs e); //declaring a delegate
public TickHandler Tick; //creating an object of delegate
public EventArgs e = null; //set 2nd paramter empty
public void Start() //starting point of thread
{
while (true)
{
System.Threading.Thread.Sleep(300);
if (Tick != null) //check if delegate object points to any listener classes method
{
Tick(this, e); //if it points i.e. not null then invoke that method!
}
}
}
}
public class Subscriber1 //1st subscriber class
{
public void Subscribe(Publisher m) //get the object of pubisher class
{
m.Tick += HeardIt; //attach listener class method to publisher class delegate object
}
private void HeardIt(Publisher m, EventArgs e) //subscriber class method
{
System.Console.WriteLine("Heard It by Listener");
}
}
public class Subscriber2 //2nd subscriber class
{
public void Subscribe2(Publisher m) //get the object of pubisher class
{
m.Tick += HeardIt; //attach listener class method to publisher class delegate object
}
private void HeardIt(Publisher m, EventArgs e) //subscriber class method
{
System.Console.WriteLine("Heard It by Listener2");
}
}
class Test
{
static void Main()
{
Publisher m = new Publisher(); //create an object of publisher class which will later be passed on subscriber classes
Subscriber1 l = new Subscriber1(); //create object of 1st subscriber class
Subscriber2 l2 = new Subscriber2(); //create object of 2nd subscriber class
l.Subscribe(m); //we pass object of publisher class to access delegate of publisher class
l2.Subscribe2(m); //we pass object of publisher class to access delegate of publisher class
m.Start(); //starting point of publisher class
}
}
Output:
Heard It by Listener
Heard It by Listener2
Heard It by Listener
Heard It by Listener2
Heard It by Listener
.
.
.
(infinite times)
Here's a simple example:
public class ObservableClass
{
private Int32 _Value;
public Int32 Value
{
get { return _Value; }
set
{
if (_Value != value)
{
_Value = value;
OnValueChanged();
}
}
}
public event EventHandler ValueChanged;
protected void OnValueChanged()
{
if (ValueChanged != null)
ValueChanged(this, EventArgs.Empty);
}
}
public class ObserverClass
{
public ObserverClass(ObservableClass observable)
{
observable.ValueChanged += TheValueChanged;
}
private void TheValueChanged(Object sender, EventArgs e)
{
Console.Out.WriteLine("Value changed to " +
((ObservableClass)sender).Value);
}
}
public class Program
{
public static void Main()
{
ObservableClass observable = new ObservableClass();
ObserverClass observer = new ObserverClass(observable);
observable.Value = 10;
}
}
Note:
This violates a rule in that I don't unhook the observer from the observable, this is perhaps good enough for this simple example, but make sure you don't keep observers hanging off of your events like that. A way to handle this would be to make ObserverClass IDisposable, and let the .Dispose method do the opposite of the code in the constructor
No error-checking performed, at least a null-check should be done in the constructor of the ObserverClass
I've tied together a couple of the great examples above (thank you as always to Mr. Skeet and Mr. Karlsen) to include a couple of different Observables and utilized an interface to keep track of them in the Observer and allowed the Observer to to "observe" any number of Observables via an internal list:
namespace ObservablePattern
{
using System;
using System.Collections.Generic;
internal static class Program
{
private static void Main()
{
var observable = new Observable();
var anotherObservable = new AnotherObservable();
using (IObserver observer = new Observer(observable))
{
observable.DoSomething();
observer.Add(anotherObservable);
anotherObservable.DoSomething();
}
Console.ReadLine();
}
}
internal interface IObservable
{
event EventHandler SomethingHappened;
}
internal sealed class Observable : IObservable
{
public event EventHandler SomethingHappened;
public void DoSomething()
{
var handler = this.SomethingHappened;
Console.WriteLine("About to do something.");
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
internal sealed class AnotherObservable : IObservable
{
public event EventHandler SomethingHappened;
public void DoSomething()
{
var handler = this.SomethingHappened;
Console.WriteLine("About to do something different.");
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
internal interface IObserver : IDisposable
{
void Add(IObservable observable);
void Remove(IObservable observable);
}
internal sealed class Observer : IObserver
{
private readonly Lazy<IList<IObservable>> observables =
new Lazy<IList<IObservable>>(() => new List<IObservable>());
public Observer()
{
}
public Observer(IObservable observable) : this()
{
this.Add(observable);
}
public void Add(IObservable observable)
{
if (observable == null)
{
return;
}
lock (this.observables)
{
this.observables.Value.Add(observable);
observable.SomethingHappened += HandleEvent;
}
}
public void Remove(IObservable observable)
{
if (observable == null)
{
return;
}
lock (this.observables)
{
observable.SomethingHappened -= HandleEvent;
this.observables.Value.Remove(observable);
}
}
public void Dispose()
{
for (var i = this.observables.Value.Count - 1; i >= 0; i--)
{
this.Remove(this.observables.Value[i]);
}
}
private static void HandleEvent(object sender, EventArgs args)
{
Console.WriteLine("Something happened to " + sender);
}
}
}
Applying the Observer Pattern with delegates and events in c# is named "Event Pattern" according to MSDN which is a slight variation.
In this Article you will find well structured examples of how to apply the pattern in c# both the classic way and using delegates and events.
Exploring the Observer Design Pattern
public class Stock
{
//declare a delegate for the event
public delegate void AskPriceChangedHandler(object sender,
AskPriceChangedEventArgs e);
//declare the event using the delegate
public event AskPriceChangedHandler AskPriceChanged;
//instance variable for ask price
object _askPrice;
//property for ask price
public object AskPrice
{
set
{
//set the instance variable
_askPrice = value;
//fire the event
OnAskPriceChanged();
}
}//AskPrice property
//method to fire event delegate with proper name
protected void OnAskPriceChanged()
{
AskPriceChanged(this, new AskPriceChangedEventArgs(_askPrice));
}//AskPriceChanged
}//Stock class
//specialized event class for the askpricechanged event
public class AskPriceChangedEventArgs : EventArgs
{
//instance variable to store the ask price
private object _askPrice;
//constructor that sets askprice
public AskPriceChangedEventArgs(object askPrice) { _askPrice = askPrice; }
//public property for the ask price
public object AskPrice { get { return _askPrice; } }
}//AskPriceChangedEventArgs
/**********************Simple Example ***********************/
class Program
{
static void Main(string[] args)
{
Parent p = new Parent();
}
}
////////////////////////////////////////////
public delegate void DelegateName(string data);
class Child
{
public event DelegateName delegateName;
public void call()
{
delegateName("Narottam");
}
}
///////////////////////////////////////////
class Parent
{
public Parent()
{
Child c = new Child();
c.delegateName += new DelegateName(print);
//or like this
//c.delegateName += print;
c.call();
}
public void print(string name)
{
Console.WriteLine("yes we got the name : " + name);
}
}
I did't want to change my source code to add additional observer , so I have written following simple example:
//EVENT DRIVEN OBSERVER PATTERN
public class Publisher
{
public Publisher()
{
var observable = new Observable();
observable.PublishData("Hello World!");
}
}
//Server will send data to this class's PublishData method
public class Observable
{
public event Receive OnReceive;
public void PublishData(string data)
{
//Add all the observer below
//1st observer
IObserver iObserver = new Observer1();
this.OnReceive += iObserver.ReceiveData;
//2nd observer
IObserver iObserver2 = new Observer2();
this.OnReceive += iObserver2.ReceiveData;
//publish data
var handler = OnReceive;
if (handler != null)
{
handler(data);
}
}
}
public interface IObserver
{
void ReceiveData(string data);
}
//Observer example
public class Observer1 : IObserver
{
public void ReceiveData(string data)
{
//sample observers does nothing with data :)
}
}
public class Observer2 : IObserver
{
public void ReceiveData(string data)
{
//sample observers does nothing with data :)
}
}
Something like this:
// interface implementation publisher
public delegate void eiSubjectEventHandler(eiSubject subject);
public interface eiSubject
{
event eiSubjectEventHandler OnUpdate;
void GenereteEventUpdate();
}
// class implementation publisher
class ecSubject : eiSubject
{
private event eiSubjectEventHandler _OnUpdate = null;
public event eiSubjectEventHandler OnUpdate
{
add
{
lock (this)
{
_OnUpdate -= value;
_OnUpdate += value;
}
}
remove { lock (this) { _OnUpdate -= value; } }
}
public void GenereteEventUpdate()
{
eiSubjectEventHandler handler = _OnUpdate;
if (handler != null)
{
handler(this);
}
}
}
// interface implementation subscriber
public interface eiObserver
{
void DoOnUpdate(eiSubject subject);
}
// class implementation subscriber
class ecObserver : eiObserver
{
public virtual void DoOnUpdate(eiSubject subject)
{
}
}
.
observer pattern C# with event
.
link to the repository

Categories