我有一个服务器应用程序,它通过网络接收信息并对其进行处理。 服务器是多线程的,并且一次处理多个套接字,并且通过BeginInvoke和EndInvoke样式方法在没有我控制的情况下创建线程,这些方法由相应的回调函数链接。

我正在尝试创建一个表单,除了主GUI之外,还显示一个ListBox项目,该项目由描述当前连接的套接字的项目填充。 所以,我基本上要做的是使用其Add()函数向ListBox添加一个项目,从该线程运行相应的回调函数。 我通过Controls属性访问我的表单控件--I:E:

(ListBox)c.Controls["listBox1"].Items.Add();

当然我不只是调用函数,我已经尝试了几种方法,我在这里和网上通过线程进行通信,包括 MethodInvoker ,使用委托,与 Invoke() BeginInvoke()等结合使用。 似乎没有任何作用,我总是得到同样的异常,告诉我我的控件是从一个创建它以外的线程访问的。

有什么想法吗?

有帮助吗?

解决方案

您必须在要访问的ListBox控件上调用Invoke(或BeginInvoke),以便在创建该控件的线程上调用委托。

ListBox listBox = c.Controls["listBox1"] as ListBox;
if(listBox != null)
{
   listBox.Invoke(...);
}

其他提示

我总是沿着这些方向使用:

        c = <your control>
        if (c.InvokeRequired)
        {
            c.BeginInvoke((MethodInvoker)delegate
            {
                //do something with c
            });
        }
        else
        {
            //do something with c
        }

我还写了一堆辅助扩展方法来帮助。

using System;
using System.ComponentModel;
public static class CrossThreadHelper
{
    public static bool CrossThread<T,R>(this ISynchronizeInvoke value, Action<T, R> action, T sender, R e)
    {
        if (value.InvokeRequired)
        {
            value.BeginInvoke(action, new object[] { sender, e });
        }

        return value.InvokeRequired;
    }
}

像这样使用:

     private void OnServerMessageReceived(object sender, ClientStateArgs e)
    {
        if (this.CrossThread((se, ev) => OnServerMessageReceived(se, ev), sender, e)) return;
        this.statusTextBox.Text += string.Format("Message Received From: {0}\r\n", e.ClientState);
    }

使用BeginInvoke或Invoke应该可以正常工作。你能发一个简短而完整的程序来证明这个问题吗?你应该能够工作一个实际上并不需要任何服务器端的东西 - 只需要一堆“假装”的线程。接收传入的连接。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top