需要帮助在 C# 中跨 UI 线程和另一个线程获取信息

发布于 2024-07-07 09:02:16 字数 567 浏览 6 评论 0原文

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

除了主 GUI 之外,我还尝试创建一个表单,该表单显示一个 ListBox 项目,其中填充了描述当前连接的套接字的项目。 因此,我基本上想做的是使用其 Add() 函数从运行适当回调函数的线程将项目添加到 ListBox。 我通过 Controls 属性访问我的表单控件 - IE:

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

当然,我不只是调用该函数,我尝试了在此处和网络上找到的几种在线程之间进行通信的方法,包括 MethodInvoker< /code>,使用委托,结合Invoke()BeginInvoke()等。 似乎没有任何效果,我总是得到相同的异常,告诉我我的控件是从创建它的线程以外的线程访问的。

有什么想法吗?

I have a server application that receives information over a network and processes it.
The server is multi-threaded and handles multiple sockets at time, and threads are created without my control through BeginInvoke and EndInvoke style methods, which are chained by corresponding callback functions.

I'm trying to create a form, in addition to the main GUI, that displays a ListBox item populated by items describing the currently connected sockets.
So, what I'm basically trying to do is add an item to the ListBox using its Add() function, from the thread the appropriate callback function is running on.
I'm accessing my forms controls through the Controls property - I.E:

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

Naturally I don't just call the function, I've tried several ways I've found here and on the web to communicate between threads, including MethodInvoker, using a delegate, in combination with Invoke(), BeginInvoke() etc.
Nothing seems to work, I always get the same exception telling me my control was accessed from a thread other than the one it was created on.

Any thoughts?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

胡渣熟男 2024-07-14 09:02:16

我总是使用这样的东西:

        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);
    }

I've always used something along these lines:

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

I also wrote a bunch of helper extension methods to... help.

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;
    }
}

used like this:

     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);
    }
萤火眠眠 2024-07-14 09:02:16

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

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

You have to call Invoke (or BeginInvoke) on the ListBox control you are accessing in order for the delegate to be called on the thread that created that control.

ListBox listBox = c.Controls["listBox1"] as ListBox;
if(listBox != null)
{
   listBox.Invoke(...);
}
辞取 2024-07-14 09:02:16

使用 BeginInvoke 或 Invoke 应该可以正常工作。 您能否发布一个简短但完整的程序来演示该问题? 您应该能够完成一个实际上不需要任何服务器端内容的工作 - 只需要一堆“假装”接收传入连接的线程。

Using BeginInvoke or Invoke should work fine. Could you post a short but complete program which demonstrates the problem? You should be able to work one up which doesn't actually need any server-side stuff - just have a bunch of threads which "pretend" to receive incoming connections.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文