我理解发布者 - 订阅者模式,但我的问题是,如果一个类的每个对象都有自己的事件处理程序副本。我搜索过SE,但大多数问题与C#: Difference between ' += anEvent' and ' += new EventHandler(anEvent)'等事件订阅签名有关。
我有一个班级:
namespace VideoClient
{
class VideoPlayer
{
Thread ClientThreadProc;
[DllImport("gdi32.dll", CharSet = CharSet.Auto)]
public static extern Int32 DeleteObject(IntPtr hGDIObj);
RtspClient client;
IntPtr hBitmap;
public string cameranameTemp;
public delegate void Source(System.Windows.Media.Imaging.BitmapSource source, Bitmap Image);
public event Source SourceHandler;
public VideoPlayer(string URL, string Username, string Password)
{
client = new RtspClient(URL);
client.Credential = new System.Net.NetworkCredential(Username, Password);
client.AuthenticationScheme = System.Net.AuthenticationSchemes.Basic;
}
public void Play()
{
client.OnConnect += (sender, args) =>
{
sender.OnPlay += (sender1, args1) =>
{
sender1.Client.FrameChangedEventsEnabled = true;
sender1.Client.RtpFrameChanged += Client_RtpFrameChanged;
sender1.Client.SetReceiveBufferSize(1024 * 1024);
};
try
{
sender.StartListening();
}
catch (Exception ex)
{
//SignalLost = true;
//IsStreaming = false;
}
};
client.OnDisconnect += (sender, args) =>
{
sender.Client.Disconnect();
sender.Client.Dispose();
sender.Disconnect();
sender.Dispose();
};
ClientThreadProc = new Thread(client.Connect);
ClientThreadProc.IsBackground = true;
ClientThreadProc.Start();
}
public void Stop()
{
if (ClientThreadProc != null)
ClientThreadProc.Abort();
client.StopListening();
}
System.Windows.Media.Imaging.BitmapSource ConvertImage(System.Drawing.Bitmap bmp)
{
if (bmp == null)
{
return null;
}
hBitmap = bmp.GetHbitmap();
System.Windows.Media.Imaging.BitmapSource bs =
System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
System.Windows.Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
DeleteObject(hBitmap);
bmp.Dispose();
return bs;
}
void Client_RtpFrameChanged(object sender, Media.Rtp.RtpFrame frame)
{
if (frame.Complete && frame.HasMarker && frame.Count > 1)
{
try
{
string temp = this.cameranameTemp; bool bTemp = client.Connected;
Application.Current.Dispatcher.Invoke
(() =>
{
if (frame.PayloadTypeByte == RFC2435Stream.RFC2435Frame.RtpJpegPayloadType && client.Listening)
{
var bitmap = (Bitmap)(new RFC2435Stream.RFC2435Frame(frame));
if (bitmap != null)
{
Bitmap image = new Bitmap(bitmap);
SourceHandler(ConvertImage(bitmap), image);
}
}
});
}
catch (Exception ex)
{ Console.WriteLine(ex.Message.ToString()); }
}
}
}
}
当我们初始化VideoPlayer类的一个实例时,每个实例都有它的类的fields / methods / delegates等的副本,但每个实例都有自己的eventhandler副本,在这种情况下; Client_RtpFrameChanged。我会这么假设,因为它是一个订阅事件的方法。但是在运行应用程序时,此事件处理程序仅处理“最后”实例的事件,并且之前初始化的所有实例似乎都没有自己的事件处理程序副本。如果确实如此,那么如何让每个实例拥有自己的eventhadler副本?
非常感谢。
答案 0 :(得分:1)
我不确定我是否完全按照你的问题......但也许这有帮助。
你有一个Class1的实例,它引发了EventA。 Class1的实例实际上是对EventA的控制。 EventA可能在任意数量的感兴趣的类中都有处理程序,但仍然只有一个Class1和一个EventA。在引发事件时调用的委托不是静态的,因此它是它自己的副本(在任何类上),但是记住委托定义的参数可以被共享,或者引发事件的类也可以共享为那些都来自于升级的Class1。