无法从 Child 表单调用参数化线程

Cant call ParametizedThread from Child Form

我正在开发 Client/server 应用程序。 在客户端应用程序中,我有一个主窗体,它是一个 MDI parent。 主窗体有一个 Load 事件,它创建一个 Child 窗体的新实例并使其可见。 此事件还将 Main 建立为 Child 的 MdiParent。 Child 表单是一个 sign-in 屏幕。 从 child 表单中,我创建了对 parent 的引用,以便能够从 parent.

调用方法

但是,在执行 MdiParent.RequestConnection 方法后,GUI 卡住了。 所以我尝试从线程执行该方法,但它不接受我的声明,即使我似乎遵循了正确的语法。 我不明白我做错了什么。请帮忙

主窗体

public partial class frmMainForm: Form
    {
        
        public frmMainForm()
        {
            InitializeComponent();
           
        }
        Thread runningClient;
        public MyTcpClient client= new MyTcpClient ();
        frmChildForm frmSignIn;
        bool clientConnected;
       

        private void frmMainForm_Load(object sender, EventArgs e)
        {
            clientConnected= false;
            panelSidebar.Hide();
            if(frmSignIn == null)
            {
                frmSignIn= new frmChildForm();
                frmSignIn.MdiParent = this;
                
                frmSignIn.Show();
            }
        }

        public void TurnOnPanels()
        {
            panelSidebar.Visible = true;
            panelSidebar.BringToFront();
        }

        public void RequestConnection(string username)
        {
            
            string serverRsp = client.Connect(username);
            if(serverRsp.Equals("SUCCESS")) 
            {
                MessageBox.Show("Signed In", "Welcome", MessageBoxButtons.OK, MessageBoxIcon.Information);
                clientConnected = true;
                frmSignIn.Close();
            }
        }
    }

还有我的child表格

public partial class frmChildForm : Form
    {
        frmMainForm frmParent;
        Thread clientRunning;
        public frmChildForm()
        {
            InitializeComponent();
            frmParent= (frmMainForm)this.MdiParent;
        }

        private void frmSignIn_FormClosing(object sender, FormClosingEventArgs e)
        {
            frmParent= (frmMainForm)this.MdiParent;
            frmParent.TurnOnPanels();
        }

        private void btnSignIn_Click(object sender, EventArgs e)
        {
            if (txtSignInUsername.Text.Equals(""))
            {
                MessageBox.Show("No empty fields.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } 
            else
            {
                //This is where it fails
                clientRunning= new Thread(new ParameterizedThreadStart(frmParent.RequestConnection);
                //"No Overload for RequestConnection matches delegate ParameterizedThreadStart"
                //If I try to include the parameter inside that call, I get a "waiting for method                      //name" syntax error message instead.
                clientRunning.Start(txtSignInUsername.Text.ToUpper());
            }
        }

        private void frmSignIn_Load(object sender, EventArgs e)
        {
            frmParent = (frmMainForm)this.MdiParent;
        }
    }

我也尝试通过在 RequestConnection 中创建一个线程来从主窗体执行此操作,它应该在其中执行 client.Connect,但我遇到了同样的错误。

您需要解决一些问题

public void RequestConnection(object username) // changed parameter type
{
    if (username == null)
        throw new ArgumentNullException(nameof(username));

    if (!(username is string))
        throw new InvalidCastException("Expect string");// give proper message

    string serverRsp = client.Connect(username.ToString());
    if (serverRsp.Equals("SUCCESS"))
    {
        MessageBox.Show("Signed In", "Welcome", MessageBoxButtons.OK, MessageBoxIcon.Information);
        clientConnected = true;

        //this is require to solve cross-thread operation
        if (this.InvokeRequired)
            this.Invoke(new MethodInvoker(delegate ()
            {
                frmSignIn.Close();
            }));
        else
            frmSignIn.Close();
    }
}

需要在Form Load Event中获取MdiParent,并从Constructor中移除。

您的子表单加载事件/或使用父更改事件

private void FrmLogin_Load(object sender, EventArgs e)
{
    frmParent = (MainForm)this.MdiParent;
}

ParametrizedThreadStart委托实际上接受一个对象作为参数。

因此您必须为其提供一个方法,该方法将对象作为参数,而不是字符串。在您的方法中,您将收到对象,检查它是否为字符串,然后将其转换为字符串。