最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

c# - Problem writing to a Control from another class and another thread - Stack Overflow

matteradmin4PV0评论

I have code that, using UDP, broadcasts the letter "P" to an Arduino WiFi.
It should broadcast 3 times with 3 seconds interval and then stop.
To monitor this, I want to see the broadcast messages sent and the messages returned from the Arduino in a RichTextBox.

As I want to a more complex program, I want to structure it and have therefore put the SendWifiString method in a class called WifiTools (which eventually will include a receive method).
I use a System.Timers.Timer to start the broadcasts, so its Elapsed event is raised in a ThreadPool Thread. In the Elapsed event handler, I generate a custom event to then write to the RichTextBox.

I have also added a button to make a broadcast for debugging.
If I test this using "Start Without Debugging" everything works fine, I see the broadcast messages in the RichTextBox, but if I use "Start Debugging" I get a "Cross-thread operation not valid: Control 'richTextBox1' accessed from a thread other than the thread it was created on."

public partial class Form1 : Form
{
    System.Timers.Timer broadcastTimer = new System.Timers.Timer();
    public int broadcastCounter = 0;
    private delegate void RichText(string text);
    WifiTools wifiTools = new WifiTools();

    public Form1()
    {
        InitializeComponent();
        StartBroadcastTimer(1000);
        wifiTools.OnRichText += WifiTools_OnRichText;
    }

    public class RichTextEventArgs : EventArgs
    {
        public string? Msg { get; set; }
    };

    public void WifiTools_OnRichText(object? sender, RichTextEventArgs e)
    {
        richTextBox1.Text += e.Msg;
    }

    class WifiTools
    {
        public event EventHandler<RichTextEventArgs>? OnRichText;
        public void SendWifiString(string sendString, string _ipAddress, int port)
        {
            try
            {
                UdpClient udpClientSendWifiString = new(_ipAddress, port);
                Byte[] sendBytes = Encoding.ASCII.GetBytes(sendString);
                udpClientSendWifiString.Send(sendBytes, sendBytes.Length);
                string richTextBoxMsg = "\nTX: to      " + _ipAddress + ":" + port + "   Msg: " + sendString;
                OnRichText?.Invoke(null, new RichTextEventArgs { Msg = richTextBoxMsg });
            }
            catch
            {
                OnRichText?.Invoke(null, new RichTextEventArgs { Msg = "Wifi Send Fail" });
            }
        }
    };

    public void StartBroadcastTimer(int broadcastInterval)
    {
        broadcastTimer.Interval = broadcastInterval;
        broadcastTimer.Start();
        broadcastTimer.Elapsed += new System.Timers.ElapsedEventHandler(Broadcast!);
    }

    private void Broadcast(object sender, EventArgs e)
    {
        string broadcastAddress = "192.168.1.255";
        int remotePort = 23921;
        wifiTools.SendWifiString("P", broadcastAddress, remotePort);
        broadcastCounter++;
        broadcastTimer.Interval = 3000;
        if (broadcastCounter > 2)
        {
            //Stops timer and releases all resources (this timer is only used at program start)
            broadcastTimer.Dispose(); 
            broadcastCounter = 0;
        }
    }     

    private void buttonBroadcast_Click(object sender, EventArgs e)
    {
        string broadcastAddress = "192.168.1.255";
        int remotePort = 23921;
        wifiTools.SendWifiString("P", broadcastAddress, remotePort);
    }
}

The exception originates from the catch statement, and occurs in the WifiTools_OnRichText() method.
If I comment out the code in the catch block:

OnRichText?.Invoke(null, new RichTextEventArgs { Msg = "Wifi Send Fail" });

then debug runs without problem, but noting is written in the RichTextBox. But I can see on my Arduino that the broadcasts were sent.

Post a comment

comment list (0)

  1. No comments so far