C#でのイベントサブスクリプションの重複を避ける
-
03-07-2019 - |
質問
イベントサブスクリプションの重複を避ける最良の方法をどのように提案しますか?このコード行が2か所で実行されると、イベントは2回実行されます。サードパーティのイベントが2回サブスクライブしないようにしています。
theOBject.TheEvent += RunMyCode;
デリゲートセッターで、これを効果的に実行できます...
theOBject.TheEvent -= RunMyCode;
theOBject.TheEvent += RunMyCode;
しかし、それが最善の方法ですか?
解決
最も効率的な方法は、この 例 :
private EventHandler _theEvent;
private object _eventLock = new object();
public event EventHandler TheEvent
{
add
{
lock (_eventLock)
{
_theEvent -= value;
_theEvent += value;
}
}
remove
{
lock (_eventLock)
{
_theEvent -= value;
}
}
}
他のヒント
これは以前に行ったことがあります。...最後のサブスクライバーが呼び出されることを受け入れられると想定しています。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
MyObject my = new MyObject();
my.Changed += new EventHandler(my_Changed);
my.Changed += new EventHandler(my_Changed1);
my.Update();
Console.ReadLine();
}
static void my_Changed(object sender, EventArgs e)
{
Console.WriteLine("Hello");
}
static void my_Changed1(object sender, EventArgs e)
{
Console.WriteLine("Hello1");
}
}
public class MyObject
{
public MyObject()
{
}
private EventHandler ChangedEventHandler;
public event EventHandler Changed
{
add
{
ChangedEventHandler = value;
}
remove
{
ChangedEventHandler -= value;
}
}
public void Update()
{
OnChanged();
}
private void OnChanged()
{
if (ChangedEventHandler != null)
{
ChangedEventHandler(this, null);
}
}
}
}
コードはマルチスレッドですか?同時実行ロックは、マルチスレッドの場合にのみ必要です。そうでない場合、オーバーヘッド。
このように、サブスクライブ解除およびサブスクライブのアプローチは正しいです。
ありがとう
theObjectのクラスのソースを所有している場合、TheEventのInvocationListにアクセスできます。イベントに独自の追加アクセサーを実装し、追加する前に確認できます。
ただし、あなたのアプローチもうまくいくと思います。
1つの詳細を除き、あなたのアプローチを使用します。サブスクライバーまたはtheObjectの新しいインスタンスを作成するときにイベントをサブスクライブする必要があると思います。これにより、コードがよりストレートになります。したがって、必要なのは、正しいオブジェクトを破棄した後に注意深く監視することだけです(このためには、パッテンを破棄するのが便利なソリューションです)。
サードパーティのイベントを使用していると述べました。つまり、アドバイスされているように、メソッドの追加/削除に独自の認識を提供することはできません。ただし、独自のイベントを持つ独自のクラスでは、問題を解決するために、イベントのメソッドの追加/削除の実現方法を独自に定義する必要があります。