Very interesting C #/. NET-safe and effective event triggering

Source: Internet
Author: User

I recently saw a good article on the Internet discussing how to safely and effectively trigger events.

Maybe you don't have to use the same solution as below, but at least you should know the problems that need to be considered when an event is triggered.

Events

It is very easy to trigger events, but there are indeed some misunderstandings. let's give an example. suppose we write a message receiver. Every time we receive a new message, we trigger an event that contains the new message.MessageReceived.

The common installation method is:

Public class MessageReceivedEventArgs: EventArgs
{
// Received message
Public string Message {get; private set ;}

// Architecture ReceivedEventArgs
Public MessageReceivedEventArgs (string message)
{
Message = message;
}
}

Next, we will create a non-thread-safe access class.UnsafeMessengerTo notify all subscribers (subscriber) at the same time ).

Public class UnsafeMessenger
{
Public event EventHandler <MessageReceivedEventArgs> MessageReceived;

// Called when a new message is received
Public void OnNewMessage (string message)
{
If (MessageReceived! = Null)
{
MessageReceived (this, new MessageReceivedEventArgs (message ));
}
}
}

Note thatOnNewMessage ()It is private, but here we set it to public for test convenience.

 

Success !! Yes? In fact, if we are a single-threaded program, this is indeed enough, but it is not thread-safe ).

Why? Think about it. A subscriber can subscribe to or unsubscribe at any time. For example, if we have a subscriber, when we receive a new message, execute this statement:

if (MessageReceived != null)
It will certainly pass, because there is a subscriber. If this subscriber executes the command to cancel the subscription at this time:
myMessenger.MessageReceived -= MyMessageHandler;
 
SoMessageReceivedThe delegate is null,

 


// The IF statement has been passed

If (MessageReceived! = Null)
{
// The MessageReceived delegate is null, but we will execute this sentence
MessageReceived (this, new MessageReceivedEventArgs (message ));
}

In this caseNullReferenceException.

 

Solution 1: Lock it, lock mechanism

When multithreading is allowed, we can use a lock mechanism to prevent a user from subscribing to or canceling a subscription when performing an event, or not triggering an event when performing an operation.


Public class SyncronizedMessenger: IMessenger
{
// Delegate and lock
Private EventHandler <MessageReceivedEventArgs> _ messageReceived;
Private readonly object _ raiseLock = new object ();

// Subscription/Unsubscribe Lock Mechanism
Public event EventHandler <MessageReceivedEventArgs> MessageReceived
{
Add {lock (_ raiseLock) {_ messageReceived + = value ;}}
Remove {lock (_ raiseLock) {_ messageReceived-= value ;}}
}



// Event Lock Mechanism

Public void OnNewMessage (string message)
{
Lock (_ raiseLock)
{
If (_ messageReceived! = Null)
{
_ MessageReceived (this, new MessageReceivedEventArgs (message ));
}
}
}

}
In this way, if someone tries to subscribe to or cancel the subscription, they must wait for the OnNewMessage event to complete, and vice versa. solution 2: Never blank. By default, a subscriber is loaded.

The main problem we are facing is that the delegate may be empty. What if we load a delegate in advance?


Public class EmptySubscriberMessenger: imesmessenger
{

// Give it an empty subscriber immediately
Public event EventHandler <MessageReceivedEventArgs> MessageReceived = (s, e) => {};


// You do not need to check whether the value is null!
Public void OnNewMessage (string message)
{
MessageReceived (this, new MessageReceivedEventArgs (message ));
}

}
Solution 3: create a local delegated copy

Another simple solution is used by many people. The recommended mode is to create a local delegated copy.


Public class LocalCopyMessenger: IMessenger
{
Public event EventHandler <MessageReceivedEventArgs> MessageReceived;


// Make a copy when an event is triggered
Public void OnNewMessage (string message)
{
Var target = MessageReceived;

If (target! = Null)
{
Target (this, new MessageReceivedEventArgs (message ));
}
}
}

The efficiency of the above four methods is as follows:

 

Translated from: C #/. NET Fundamentals: Safely and Efficiently Raising Events

Summary

There is a Programming method called Cargo Cult Programming. Chinese name: Goods worship Programming. Wikipedia is defined"

The feature is to use code or program architecture in an uncertain manner. Cargo worship programming is usually a typical manifestation of a programmer neither understanding the bugs he wants to solve nor understanding the apparent solutions.

This term sometimes refers to an unfamiliar or inexperienced programmer copying code from one place to another, but it is not clear how the code works, or it is unclear whether this code is needed in the new place. It can also be an incorrect or excessive application design pattern, code style or programming method, but its principle is not clear. "

I admit that in "holding high pragmatism" (How do people make a happy ASP. for efficiency, I often do this. -- Who has time to test third-party controls?

Since this scheme for creating local delegated copies was recommended by the experts, everyone is using it, and some people may not understand the story behind it.

Some friends who have time can talk about the wild history in. net and expand their programming capabilities. This is more beneficial than chatting about which star has been potential rules ~~~

This year's Summary + New Year's greetings

It may be the last article of this year. Below is a list of my blog posts today. I wish you a happy New Year!

 

* Programmer life

Sometimes, as a programmer, we just need to be restarted.

How to maintain and improve combat effectiveness

How to be a happy ASP. NET programmer

 

* C # Language

Topic set for writing elegant and concise code-Csharp (C #) [1]

Topic set for writing elegant and concise code-Csharp (C #) [2]

Let's talk about Csharp (C #) "neat code" -- getting smaller [1]

 

C # Wonderful functions-8. String Remove () and Replace ()

The wonderful functions in C #-7. String Split and Join

C # Wonderful functions-6. Five sequence aggregation operations (Sum, Average, Min, Max, Aggregate)

C # Wonderful functions-5. Nullable static class

C # Wonderful functions -- 4. Empty, DefaultIfEmpty, Count

A wonderful function in C #-3. Five Simple Methods for connecting Sequences

C # Wonderful functions -- 2. First and Single -- are you the First or only one in her mind?

C # Wonderful functions -- 1. ToLookup

 

Unknown C # basics 4. Delayed loading-Improving Performance

Unknown C # basics 3. Thread Analysis

C # basics 2. -- start with the similarities and differences between struct and class

Unknown C # basics 1. -- Extension Method

 

* Others

Evolution from Comparison/Converter to Func

Quickly generate HTML, EXCEL, and CSV reports from Linq Queries

DynamicXml-XML for dynamic read Operations (a general implementation from XML to Object)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.