C# C属性和属性更改线程失败

C# C属性和属性更改线程失败,c#,multithreading,properties,locking,polymorphism,C#,Multithreading,Properties,Locking,Polymorphism,最后,我接收到线程无法访问,因为它属于另一个线程。但是,这并不直接与UI相关。只有当我试图设置对象的属性而不是成员本身时,才会引发异常。如果直接设置成员,效果很好,但我会丢失PropertyChanged事件。如果我把事情搞得太复杂了,请告诉我!我想不出其他方法将属性返回MainWindow 您可以快进到下面的第3类以获取结果。在最高级别上,我涉及三个类:MainWindow、OCXComms和ZServer。当按下listen按钮时,它将调用OCXComms中的启动方法,并负责创建ZServe

最后,我接收到线程无法访问,因为它属于另一个线程。但是,这并不直接与UI相关。只有当我试图设置对象的属性而不是成员本身时,才会引发异常。如果直接设置成员,效果很好,但我会丢失PropertyChanged事件。如果我把事情搞得太复杂了,请告诉我!我想不出其他方法将属性返回MainWindow

您可以快进到下面的第3类以获取结果。在最高级别上,我涉及三个类:MainWindow、OCXComms和ZServer。当按下listen按钮时,它将调用OCXComms中的启动方法,并负责创建ZServer实例,如图所示:

第一类

接下来,通过StartOutput在主线程上构造ZServer对象。这个很好用

第二类

这就是问题所在。请注意,这里只显示了两种不同的尝试,而不是实际的语法。如果没有断点,客户端和服务器就会挂起,如果设置了断点,第一个更改异常会通知我某个线程正在尝试访问另一个线程拥有的信息。我有点清楚,ZServer是在主线程上创建的,现在我在侦听器线程上。我毫不怀疑这就是问题所在。然而,我不确定如何进行。我的大部分研究都指向Dispatcher,但我不在它的主窗口中。。。。我有三个班深;我尝试过锁定、监视、新线程,但都没有成功。如有任何建议,将不胜感激

第三类


这里的问题很简单,您在一个线程上创建一个表单,使该线程成为该表单的UI线程。然而,在服务器中,您启动了一个新线程,该线程不拥有连接客户端时引发事件的窗体,并通过处理程序将该事件传播到comms_IsClient ConnectedChanged。但是,该传播仍然在该工作线程上,而不是在UI线程上

因此,当处理程序代码调用connectionStatusLbl.Content时,它会通过非UI拥有线程调用UI控件。这是不可能的


在访问窗体或其任何子控件时,在comms_IsClient ConnectedChanged内部使用.InvokeRequired和.Invoke。这会解决你的问题。

我根本不会去那里看。谢谢你的帮助!我的眼睛要歪了。
public partial class MainWindow : Window
{
    private OCUComms comms;

        ......

    private void roxListenBtn_Click(object sender, RoutedEventArgs e)
    {
        //Debugger Shows Main Thread
        comms.StartOutput();
    }

   void comms_IsClientConnectedChanged(object sender, PropertyChangedEventArgs e)
    {
        connectionStatusLbl.Content = "Connected - No Control";
        connectionStatusLbl.Foreground = myWarningBrush;

        roverControlBtn.IsEnabled = true;
        manualControlRB.IsEnabled = true;
    }

        ......
}
public sealed class OCXComms : INotifyPropertyChanged
{

        private static OCXComms instance;
        private static readonly object instanceSync = new object();

        private Boolean _isClientConnected = false;
        private bool isEnabled;

          .....

     public static OCXComms Instance
    {
        get
        {
            if (instance == null)
            {
                lock (instanceSync)
                {
                    if (instance == null)
                        instance = new OCXComms();
                }
            }

            return instance;
        }
    }

    private OCXComms()
    {
        isEnabled = false;
        _isControllerEnabled = false;
        _isKeyboardEnabled = false;

        worker = new System.Timers.Timer();

        worker.Elapsed += new ElapsedEventHandler(worker_Elapsed);

        Properties.Settings.Default.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Default_PropertyChanged);
    }

     public event PropertyChangedEventHandler PropertyChanged;


    private void OnClientConnectedChanged()
    {
        if (PropertyChanged != null)

            PropertyChanged(this, new PropertyChangedEventArgs("IsClientConnected"));
    }

    void server_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        this.IsClientConnected = server.getIsClientConnected();
    } 

        public void StartOutput()
    {
            if (isEnabled)
                return;

            Console.WriteLine("ZServer started on: " + Thread.CurrentThread.Name);

            //Debugger Shows Main Thread
            this.server = new ZServer(Properties.Settings.Default.ListeningPort);
            this.server.PropertyChanged += server_PropertyChanged;
            this.server.Start();

            IsEnabled = true;

    }
}
public class ZServer
{
    private Thread listenThread;
    private Boolean _isClientConnected = false;

    public ZServer(String sIP, int iPort)
    {
        InitializeServer(sIP, iPort);
    }

       private void InitializeServer(String sIP, int iPort)
    {
        this.tcpListener = new TcpListener(IPAddress.Parse(sIP), iPort);
        this.listenThread = new Thread(new ThreadStart(ListenForClients_DoWork));
        this.listenThread.Name = "Listen Thread";

    }

            public Boolean IsClientConnected
    {
        get 
        {
        return _isClientConnected;
        }

        private set 
        {
            _isClientConnected = value;
            OnClientConnectedChanged();
        }
    }

    private void OnClientConnectedChanged()
    {
        if (PropertyChanged != null)

            PropertyChanged(this, new PropertyChangedEventArgs("IsClientConnected"));
    }


     private void ListenForClients_DoWork()
    {
        // Start the Server Listening for Clients to connect while blocking.
        this.tcpListener.Start();

        while (!tokenSource.Token.IsCancellationRequested)
        {
            try
            {

                TcpClient client = this.tcpListener.AcceptTcpClient();

                this._isClientConnected = true;  //<== This Works
                this.IsClientConnected = true; //This causes client and server to hang. Possible deadlock?
                ........
            }
            catch (SocketException socketEx)
            {
                Console.WriteLine("Socket Closed from Another Thread: " + socketEx.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine("ZServer: unhandled exception in ListenForClients: " + ex.Message);
            }
        }
        Console.WriteLine("ListenForClients exiting...");
    }

    public Boolean getIsClientConnected()
    {
        lock (_clientConnectedLock)
        {
            return _isClientConnected;
        }
    }   

}