调整控件

时间:2017-04-26 19:38:40

标签: c# windows winforms user-controls tcpclient

在C#Winforms项目中,我有一个UserControl类,它将TcpClient作为私有成员。 当用户拖动或以其他方式调整UserControl的父类的大小时,TcpClient设置为null。当UserControl的父级开始最大化或最小化时,TcpClient不会设置为null。处理TcpClient的代码在单独的thead中运行。我还没有找到任何其他用户遇到此问题。

我尝试在UserControl的构造函数和析构函数上设置断点,但无济于事。代码如下所示:

public partial class IPCInterface: UserControl
{
    private TcpClient aClient = null;
    private bool IsRunning = true;
    private Thread ShellThread = null;
    // [SNIP]
    private void MainLoop()
    {
        // The exception occurs in this function when resizing
        try
        { 
            // The exception is thrown here, aClient.Client.Get returns null -> nullreference exception
            while (IsRunning && aClient.Client.Connected == true)
            {
                while (aClient.Client.Available > 0)
                    ShellInputOutputBox.Invoke(
                        (MethodInvoker)delegate () 
                        {
                            ShellInputOutputBox.Text += ReceiveString();
                        });

                Thread.Sleep(100);
            }

            if(aClient.Client.Connected == true)
                aClient.Client.Close();
        }
        catch(Exception e)
        {
            MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);  // The exception occurs here when resizing
        }

    }

    public IPCInterface(TcpClient IPCStream)
    {
        InitializeComponent();

        aClient = IPCStream;
        ShellThread = new Thread(() => MainLoop());
        ShellThread.Start();
    }

我知道为什么会发生这种情况。有人知道如何抵消插座的关闭吗?

其他信息:

UserControl本身位于选项卡界面内,该选项卡界面也位于选项卡界面中(我不是UX设计师......)。所有这些接口都锚定到其父级的外边缘,以便在用户调整主窗体大小时移动它们。

1 个答案:

答案 0 :(得分:0)

我已经解决了这个问题。事实证明,这是一个对象所有权问题,结合winforms在调整表单大小时显然会触发垃圾收集这一事实。

代码中的其他地方我创建了UserControl使用的连接,如下所示:

        public static TcpClient OpenSession(string ServerIp, int ServerPort)
        {
            cServerControl Result = new cServerControl(ServerIp, ServerPort);
            Result.Connect();

            // [SNIP]

            return Result.TcpClient;
        }

我认为C#的结论是,由于cServerControl是在一个线程中创建的,该线程与稍后将与TcpClient交互的线程分开,因此它可以安全地处理TcpClient。忽略TcpClient显式转移到新线程的事实。更改代码以返回cServerControl(并使用UserControl中的cServerControl而不是TcpClient)修复了该问题,因为cServerControl现在未标记为可处置。