You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从其他类线程调用UI方法?UDP监听线程传参问题

问题解决:UDP监听线程传递数据到UI方法

我的UDP监听类线程运行正常,但不知道如何把recData字符串传递给UI方法UpdateCommand?我已经在UpdateCommand里用了Dispatcher,但不知道怎么在ListenForUDPPackages()里调用这个方法,试了好几种调用方式都不行,求帮忙。

namespace SoftEKA
{
   
    
    public delegate void OnDataReceivedHandler(string newData);
    public class UDPListener
    {
        private int portToListen = 5001;
        private volatile bool listening;
        Thread UDPListeningThread;
        public string recData;
        public event OnDataReceivedHandler DataReceived;

        // constructor
        public UDPListener()
        {
            this.listening = false;
        }

        // starts the UDPListener-Thread
        public void StartListener(int exceptedMessageLength)
        {
            if (!this.listening)
            {
                UDPListeningThread = new Thread(ListenForUDPPackages);
                this.listening = true;
                UDPListeningThread.Start();
            }
        }
        // stops the UDPListener-Thread
        public void StopListener()
        {
            this.listening = false;
        }
 
        // receives incoming UDP-Messages
        public void ListenForUDPPackages()
        {      
            UdpClient listener = null;
            try
            {
                listener = new UdpClient(portToListen);
            }
            catch (SocketException)
            {
                //do nothing
            }

            if (listener != null)
            {
                {
                    IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, portToListen);
                    //MainWindow MW = new MainWindow();

                    try
                    {
                        while (true)
                        {
                            // received message as array of byte
                            byte[] data = listener.Receive(ref groupEP);

                            Console.WriteLine($"Received broadcast from {groupEP} :");
                            Console.WriteLine($"{Encoding.ASCII.GetString(data, 0, data.Length)}");
                            recData = Encoding.ASCII.GetString(data, 0, data.Length);
                            MessageBox.Show(recData);

                             ------>  here!! Calling the UI-method UpdateCommand(recData)

                            if (DataReceived != null)
                                DataReceived(recData);
                            else
                                Console.WriteLine("Null ausgeloest");
                        }
                    }
                    catch (SocketException e)
                    {
                        Console.WriteLine(e);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.ToString());
                    }
                    finally
                    {
                        listener.Close();
                        Console.WriteLine("Done listening for UDP broadcast");
                    }
                }
            }
        }
    }


    
    public partial class MainWindow : Window
    {
        SoundPlayer soundPlayer = new SoundPlayer(@"c:\Users\Klaus\Music\beep.wav");

        Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        IPEndPoint ep = new IPEndPoint(IPAddress.Parse("192.168.178.255"), 5000);

        UDPListener listener = new UDPListener();


    
        public MainWindow()
        {
            InitializeComponent();

            listener.StartListener(1024);

        }


       public void UpdateCommand(string data)
        {
            this.Dispatcher.Invoke(() => { Command.Text = data; });
        }
}

解决方法

你已经定义了DataReceived事件,这是解耦UDP监听逻辑和UI逻辑的正确方式,不需要在UDPListener类里直接调用UI方法,按以下步骤修改:

  • 在MainWindow构造函数中订阅事件
    修改MainWindow的构造函数,添加事件订阅:

    public MainWindow()
    {
        InitializeComponent();
        // 订阅DataReceived事件,收到数据时触发处理方法
        listener.DataReceived += Listener_DataReceived;
        listener.StartListener(1024);
    }
    
  • 实现事件处理方法
    在MainWindow中添加事件处理方法,调用你的UpdateCommand:

    private void Listener_DataReceived(string newData)
    {
        UpdateCommand(newData);
    }
    
  • 修复UDPListener的循环控制
    你当前的while(true)会导致StopListener方法失效,改成用listening变量控制循环:

    // 替换ListenForUDPPackages中的while循环
    while (listening)
    {
        byte[] data = listener.Receive(ref groupEP);
    
        Console.WriteLine($"Received broadcast from {groupEP} :");
        Console.WriteLine($"{Encoding.ASCII.GetString(data, 0, data.Length)}");
        recData = Encoding.ASCII.GetString(data, 0, data.Length);
        // 注意:后台线程不能直接调用MessageBox,如需弹窗请用Dispatcher
        // Application.Current.Dispatcher.Invoke(() => MessageBox.Show(recData));
    
        DataReceived?.Invoke(recData); // 简化事件触发写法
    }
    
  • 优化事件触发写法
    把原来的if (DataReceived != null) DataReceived(recData);改成空合并运算符的写法DataReceived?.Invoke(recData);,更简洁安全。

这样修改后,UDP监听线程收到数据时会触发DataReceived事件,MainWindow订阅该事件后调用UpdateCommand,通过Dispatcher更新UI元素,完全符合WPF的线程模型要求。


内容的提问来源于stack exchange,提问作者Klaus Dilper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 18:15:10