【问题标题】:Need help getting info across a UI thread and another thread in C#需要帮助在 C# 中跨 UI 线程和另一个线程获取信息
【发布时间】:2008-10-23 10:31:59
【问题描述】:

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

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

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

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

有什么想法吗?

【问题讨论】:

  • 一个相关的微妙之处是,如果您正在从控件读取,您通常希望使用 Invoke 而不是 BeginInvoke 来确保在继续之前填充当前线程中的目标变量。我认为我们还没有未来。 :)

标签: c# forms invoke multithreading


【解决方案1】:

我一直使用这些方面的东西:

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

【讨论】:

  • 为什么不只有一种扩展方法接受 Action 或 MethodInvoker?干净多了,调用者总是可以在delegate中填写其余部分
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 2011-08-22
      相关资源
      最近更新 更多