Hello dear readers and coders
Welcome to the second ‘Can You Spot the Deadlock?’ trivia. I surely hope you had fun with the first one. Yeah, I know, it was kinda easy. So today, I raise the bar a bit and bring you one of my favorites: the transactional subscription/un subscription pattern.
The code compiles but it will not run, as I did not show the scaffolding code. Suffice to say that there is a notification mechanism that lives in its own thread(s) and some client code logic that rely on the main(starting) thread.
So:
- What is the issue here?
- Where does it occur?
- Can you fix it ? if yes how, if now, why
Problem is now closed, please find the solution
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SpotTheDeadLock2
{
///
/// Implements aynchronous notification
///
public class EventSource
{
private EventHandler _eventHandler;
///
/// notification event
///
public event EventHandler EventOccured
{
add {
// lock to secure subscription
lock (this){
_eventHandler += value;
}
}
remove {
// lock to secure unsubscription
lock (this) {
_eventHandler -= value;
}
}
}
// implementation of notification
private void TriggerEvent() {
lock (this) {
if (_eventHandler != null) {
_eventHandler(this, new EventArgs());
}
}
}
}
///
/// client implementation
///
public class Client: IDisposable
{
private EventSource _source;
///
/// Simple constructor
///
///data source to subsribe to
public Client(EventSource source) {
_source = source;
_source.EventOccured += OnEvent;
}
///
/// Method in charge of processing events
///
private void OnEvent(object sender, EventArgs arguments) {
// use lock as we do not have control of calling thread
lock (this) {
// do my job
...
}
}
// unsubscribe on clean up
public void Dispose() {
// use lock to ensure no processing is in progress
lock (this) {
_source.EventOccured -= OnEvent;
}
}
}
}