【问题标题】:Windows Form Application with UDP使用 UDP 的 Windows 窗体应用程序
【发布时间】:2013-07-23 08:30:18
【问题描述】:

我正在尝试显示从服务器发送到客户端的一些数据。客户端脚本是一个 Windows 窗体应用程序,我有一个名为 label1 的标签,我试图将其文本显示为从服务器客户端接收到的数据,但 label1 的文本根本不会改变。这是什么原因?下面是客户端代码。服务器脚本是一个控制台应用程序。

现在 Program.cs 是空的,Form1.cs 看起来像这样,但 label1.text 仍然出现相同的错误:

namespace WindowsFormsApplication4
{
    public partial class Form1 : Form
    {
        public Form1() { InitializeComponent(); }

        private void Form1_Load(object sender, EventArgs e)
        {
            GetDataFromUDP();
        }

        public static void SetTextForLabel(string myText)
        {

            label1.Text = myText;
        }

        private void GetDataFromUDP()
        {
            UdpClient subscriber = new UdpClient(8899);
            IPAddress addr = IPAddress.Parse("230.0.0.1");
            subscriber.JoinMulticastGroup(addr);
            IPEndPoint ep = null;
            for (int i = 0; i < 10; i++)
            {
                byte[] pdata = subscriber.Receive(ref ep);
                string price = Encoding.ASCII.GetString(pdata);
                //Write data to the label
                SetTextForLabel(price);
            }
            subscriber.DropMulticastGroup(addr);
        }
    }
}

在 SetTextForLabel 里面我得到了错误:

An object reference is required for the non-static field, method, or property 'WindowsFormsApplication4.Form1.label1'



public static void SetTextForLabel(string myText)
{

   label1.Text = myText;
}

【问题讨论】:

    标签: c# winforms udp


    【解决方案1】:

    静态方法SetTextForLabel 无权访问类Form1 的实例的控件。您必须通过在Form1 类中传递参数或声明静态成员来提供特定实例。

    正如 cmets 中所述,这也不起作用,因为 Application.Run() 在当前线程中启动了一个应用程序,因此代码也需要一些重构。

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            ConnectUDP();
        }
    
        private void ConnectUDP()
        {
            UdpClient subscriber = new UdpClient(8899);
            IPAddress addr = IPAddress.Parse("230.0.0.1");
            subscriber.JoinMulticastGroup(addr);
            IPEndPoint ep = null;
            for (int i = 0; i < 10; i++)
            {
                byte[] pdata = subscriber.Receive(ref ep);
                string price = Encoding.ASCII.GetString(pdata);
                //Write data to the label
                label1.Text += price;
            }
            subscriber.DropMulticastGroup(addr);
        }
    }
    

    然后在Main():

    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
    

    【讨论】:

    • Application.Run 是不是阻塞了?
    • 是的,你是对的。您应该在表单的构造函数、方法或按钮单击处理程序上运行 UDP 连接的代码。如果您不希望连接阻止表单,那就另当别论了。
    • @juan facorro 我不再收到任何错误,但标签的文本没有改变。
    • @HarrisCalvin 那是因为正如 Sriram Sakthivel 所提到的,Application.Run() 会阻塞当前线程,因此在关闭表单之前不会执行 UDP 代码。我编辑了答案,以便在创建表单时建立 UDP 连接。
    • @juan.facorro 在原始帖子中编辑了我的代码。仍然出现同样的错误。
    【解决方案2】:

    看起来像线程问题。我希望 UDP 调用在池线程的后台运行,这样它就不会阻塞 UI。只需更改获取对象的方法,然后就可以异步调用它。然后我有一个小例程来检查控件是否可以直接更新,否则它只会在主 UI 线程上调用。

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            // initialise the ConnectUDP method on a pooled thread
            // Note: could do this from the onLoad event too
            System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(ConnectUDP));
    
        // This function just invokes the main UI thread if required
        private static void UIThread(Control c, MethodInvoker code)
        {
            if (control.InvokeRequired)
            {
               control.BeginInvoke(code);
               return;
            }
            control.Invoke(code);
        }
    
        private void ConnectUDP(object obj)
        {
            UdpClient subscriber = new UdpClient(8899);
            IPAddress addr = IPAddress.Parse("230.0.0.1");
            subscriber.JoinMulticastGroup(addr);
            IPEndPoint ep = null;
            for (int i = 0; i < 10; i++)
            {
                byte[] pdata = subscriber.Receive(ref ep);
                string price = Encoding.ASCII.GetString(pdata);
                // Update the label on the main UI thread
                UIThread(label1, delegate {
                    label1.Text += price;
                });
            }
            subscriber.DropMulticastGroup(addr);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-02
      • 2015-08-25
      相关资源
      最近更新 更多