admin管理员组

文章数量:1025481

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.

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.

本文标签: cProblem writing to a Control from another class and another threadStack Overflow