You are seeing a code written to see time data from Rasberry pi in a text box named textBox1 in a c# windows form application on another computer. When run, the print statements work fine but the form does not load.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
namespace WindowsFormsApp4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Console.WriteLine("Trying to establish connection...");
TcpClient client = new TcpClient();
client.Connect("192.168.104.15", 4900);
Console.WriteLine("Connection established.");
NetworkStream stream = client.GetStream();
byte[] buffer = new byte[1];
int bytesReceived;
while (true)
{
bytesReceived = stream.Read(buffer, 0, buffer.Length);
if (bytesReceived == 0)
break;
Console.WriteLine("Data received.");
string receivedData = System.Text.Encoding.ASCII.GetString(buffer, 0, bytesReceived);
textBox1.Text = receivedData;
Array.Clear(buffer, 0, buffer.Length);
Console.WriteLine("Data printed.");
}
client.Close();
}
}
}
I did the same process from python to python, it was working fine. I haven't done anything specific to this problem for C#.
CodePudding user response:
The
while(true)
is blocking the UI thread. So the load form never finish. Try putting the while(true) to a new thread. so the Winform UI thread is not blocked.
CodePudding user response:
Your code shows an attempt read a TCP connection and your comment clarifies that you "want to receive data in an infinite loop". One way to achieve this outcome without blocking the main form's load method is to do your IO using async
methods:
public partial class MainForm : Form
{
public MainForm() => InitializeComponent();
protected override void onl oad(EventArgs e)
{
base.OnLoad(e);
_tcpTask = execTcpPingLoop();
}
private Task? _tcpTask = null;
private async Task execTcpPingLoop()
{
Console.WriteLine("Trying to establish connection...");
using (TcpClient client = new TcpClient())
{
try
{
await client.ConnectAsync(
"192.168.104.15",
4900,
new CancellationTokenSource(TimeSpan.FromSeconds(5)).Token
);
Console.WriteLine("Connection established.");
byte[] buffer = new byte[1];
int bytesReceived;
while (true)
{
using (NetworkStream stream = client.GetStream())
{
bytesReceived = await stream.ReadAsync(buffer, 0, buffer.Length);
}
if (!bytesReceived.Equals(0))
{
Console.WriteLine("Data received.");
string receivedData = System.Text.Encoding.ASCII.GetString(buffer, 0, bytesReceived);
textBox1.AppendText(receivedData);
Array.Clear(buffer, 0, buffer.Length);
Console.WriteLine("Data printed.");
}
}
}
catch (Exception ex)
{
Debug.Assert(false, ex.Message);
}
}
}
}
Test
Since I don't have access to your TCP connection, here's the code I used to test this answer:
public partial class MainForm : Form
{
public MainForm() => InitializeComponent();
protected override void onl oad(EventArgs e)
{
base.OnLoad(e);
_tcpTask = execTcpPingLoop();
}
private Task? _tcpTask = null;
private async Task execTcpPingLoop()
{
Console.WriteLine("Trying to establish connection...");
using (TcpClient client = new TcpClient())
{
try
{
richTextBox.Append("Trying to establish connection...", color: Color.Blue);
while (true)
{
var pingReply = new Ping().Send(
"www.google.com",
timeout: (int)TimeSpan.FromSeconds(10).TotalMilliseconds,
buffer: new byte[0],
options: new PingOptions(64, true));
richTextBox.Append($"{pingReply.Status}: Elapsed={pingReply.RoundtripTime}");
// Wait out the delay asynchronously
await Task.Delay(1000);
}
}
catch (Exception ex)
{
Debug.Assert(false, ex.Message);
}
}
}
}
Where Append
is an extension for RichTextBox
:
static class Extensions
{
public static void Append(this RichTextBox @this, string? text = null, bool newLine = true, Color? color = null)
{
if (newLine && !string.IsNullOrWhiteSpace(text))
{
text = $"{text}{Environment.NewLine}";
}
if (color != null)
{
var colorB4 = @this.ForeColor;
@this.SelectionColor = (Color)color;
@this.AppendText(text);
@this.SelectionColor = colorB4;
}
else @this.AppendText(text);
}
}