所有对象只有一个事件处理程序的副本

时间:2014-08-29 09:18:51

标签: wpf winforms c#-4.0

我理解发布者 - 订阅者模式,但我的问题是,如果一个类的每个对象都有自己的事件处理程序副本。我搜索过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副本?

非常感谢。

1 个答案:

答案 0 :(得分:1)

我不确定我是否完全按照你的问题......但也许这有帮助。

你有一个Class1的实例,它引发了EventA。 Class1的实例实际上是对EventA的控制。 EventA可能在任意数量的感兴趣的类中都有处理程序,但仍然只有一个Class1和一个EventA。在引发事件时调用的委托不是静态的,因此它是它自己的副本(在任何类上),但是记住委托定义的参数可以被共享,或者引发事件的类也可以共享为那些都来自于升级的Class1。

相关问题