I'm trying to create a simple GUI implementation of the ping program. I have a form which is just a text box textBox1 where users enter the IP as a string, press a button Ping, and the result of the ping is displayed in a label label1. For some reason the text wont show up when I run the program.
Code partially taken from Ping.SEndAsync:
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.IO;
using System.Threading;
using System.Net.NetworkInformation;
using System.Net;
namespace pinger
{
public partial class Form1 : Form
{
private string address;
private string response;
private PingReply reply;
//public string response;
private void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
if (e.Cancelled)
((AutoResetEvent)e.UserState).Set();
if (e.Error != null)
((AutoResetEvent)e.UserState).Set();
reply = e.Reply;
((AutoResetEvent)e.UserState).Set();
if (reply == null)
return;
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
address = IPtextbox.Text;
}
private void Ping_click(object sender, EventArgs e)
{
AutoResetEvent waiter = new AutoResetEvent(false);
Ping pingSender = new Ping(); //creates a new 'pingSender' Ping object
pingSender.PingCompleted +=
new PingCompletedEventHandler(PingCompletedCallback);
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 1000;
pingSender.SendAsync(address, timeout, buffer, waiter);
}
private void label1_Click(object sender, EventArgs e)
{
label1.Text = "the ping was: " + reply.Status.ToString();
Show();
Refresh();
}
}
}
According to your code you label only changes it's text when you click on it. label1_Click event is raised.
PingCompleted event to get information about the completion status and data collected by a call to the SendAsync methods. In it you can change your label text with the result of the ping.
Add all the code inside label1_Click to PingCompletedCallback method as follows;
private void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
if (e.Cancelled || e.Error != null)
((AutoResetEvent)e.UserState).Set();
reply = e.Reply;
if (reply == null)
return;
//Change the label here
label1.Text = "the ping was: " + reply.Status.ToString();
Show();
Refresh();
}
Related
I am tasked with creating a Windows form application for the factory i work for.
We will be weighing multiple bags, so every time the button is pressed it must send the weight that is currently on the scale. In other words just capture the current weight and wait for me to press the button again to capture the next bag that will be loaded on the scale. Currently it continuously receives data from the scale once the button is clicked and the result only flashes in my textbox. I want to change so it only receives one weight then stops. Can you please show me how i can accomplish this.
Thank you in advance
Below is my code:
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.IO.Ports;
using Microsoft.Office.Interop.Excel;
namespace ScaleV5
{
public partial class Form1 : Form
{
private SerialPort _serialPort; //<-- declares a SerialPort Variable to be used throughout the form
private const int BaudRate = 9600; //<-- BaudRate Constant. 9600 seems to be the scale-units default value
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string[] portNames = SerialPort.GetPortNames(); //<-- Reads all available comPorts
foreach (var portName in portNames)
{
comboBox1.Items.Add(portName); //<-- Adds Ports to combobox
}
comboBox1.SelectedIndex = 0; //<-- Selects first entry (convenience purposes)
}
private void button1_Click(object sender, EventArgs e)
{
//<-- This block ensures that no exceptions happen
if (_serialPort != null && _serialPort.IsOpen)
_serialPort.Close();
if (_serialPort != null)
_serialPort.Dispose();
//<-- End of Block
_serialPort = new SerialPort(comboBox1.Text, BaudRate, Parity.None, 8, StopBits.One); //<-- Creates new SerialPort using the name selected in the combobox
_serialPort.DataReceived += SerialPortOnDataReceived; //<-- this event happens everytime when new data is received by the ComPort
_serialPort.Open(); //<-- make the comport listen
textBox1.Multiline = true;
textBox1.Text += $"Listening on " + _serialPort.PortName + $"\r\n";
}
private delegate void Closure();
private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
if (InvokeRequired) //<-- Makes sure the function is invoked to work properly in the UI-Thread
BeginInvoke(new Closure(() => { SerialPortOnDataReceived(sender, serialDataReceivedEventArgs); })); //<-- Function invokes itself
else
{
int dataLength = _serialPort.BytesToRead;
byte[] data = new byte[dataLength];
int nbrDataRead = _serialPort.Read(data, 0, dataLength);
if (nbrDataRead == 0)
return;
string str = System.Text.Encoding.UTF8.GetString(data);
textBox1.Text = str.ToString();
_serialPort.WriteLine("w");
}
}
private void button2_Click(object sender, EventArgs e)
{
textBox1.Clear();
}
private void button3_Click(object sender, EventArgs e)
{
_serialPort.Close();
this.Close();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void button4_Click(object sender, EventArgs e)
{
}
}
}
put the entire port instantiation and closing/opening code into the SelectedIndexChanged event of the combobox. When the user chooses a port you simply open it and leave it open. Opening and closing ports takes time. So you should keep it to a minimum.
When pressing the button you would only probe the scale via the port for the values. (If you really have 2 modes of operation choose the single measurement)
private void button1_Click(object sender, EventArgs e)
{
// probe device for value
_serialPort.WriteLine("w");
Thread.Sleep(100);
string response = _serialPort.ReadExisting();
// here parse the resonse to extract you value
// stop the device
_serialPort.WriteLine("w");
textBox1.Multiline = true; // <- this code belongs into the constructor
textBox1.Text += extractedStringValue;
}
disclaimer: this code runs synchronously and will block the UI. It depends strongly on your device how long it need to responde to your first request of measurements. To avoid the blocking of the UI you would need to work with async/await.
i am sending Sensor information with a NUCLEOF411RE to my PC. I receive this data on the COM98 with a BaudRate of 115200. Now i want to program a Windows Application that will split my string and put it on my textboxes. until now i display the data with a Button_click event. It puts values on the Textboxes that actually are the real values. But if i move my Sensor and klick the button again there should be a lot more different values, but there are the same values on the textboxes. In addition i want to refresh the textboxes automatically and not with a button click.
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.IO.Ports;
namespace BNO080
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
getAvailablePorts();
}
public string comport;
SerialPort serial = new SerialPort();
void getAvailablePorts()
{
String[] ports = SerialPort.GetPortNames();
comboBox1.Items.AddRange(ports);
comport = comboBox1.Text;
}
private void button1_Click(object sender, EventArgs e)
{
try
{
if(comboBox1.Text=="" || textBox6.Text=="")
{
MessageBox.Show("Please Select Port Settings");
}
else
{
serial.PortName = comboBox1.Text;
serial.BaudRate = Convert.ToInt32(textBox6.Text);
serial.Parity = Parity.None;
serial.StopBits = StopBits.One;
serial.DataBits = 8;
serial.Handshake = Handshake.None;
serial.Open();
MessageBox.Show("connected!");
}
}
catch (UnauthorizedAccessException)
{
MessageBox.Show("Unauthorised Access");
}
}
private void button2_Click(object sender, EventArgs e)
{
textBox1.Clear();
textBox2.Clear();
textBox3.Clear();
textBox4.Clear();
textBox5.Clear();
MessageBox.Show("connection closed!");
serial.Close();
}
private void button3_Click(object sender, EventArgs e)
{
try
{
textBox5.Text = serial.ReadLine();
/*String[] Stringsizes = A.Split(new char[] {' '});
textBox1.Text = Stringsizes[0];
textBox2.Text = Stringsizes[1];
textBox3.Text = Stringsizes[2];
textBox4.Text = Stringsizes[3];*/
// textBox5.Text = A;
//Array.Clear(Stringsizes, 0, 3);
}
catch (Exception) { }
}
}
}
can someone help me?
Can you give more information why you use the Button_Click Event to read the text? Maybe it is a possible way for you to subscribe for the DataReceived-Event of the COM-port?
It would look something like this:
serial.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
string receivedString = serial.ReadExisting();
//Do something here...
}
I'd do a couple things. First subscribe to the DataReceived event on the serial port. This event handler will get called when there is data available on the serial port. Then in the event handler you can read from the serial port and add it to your textbox. You can't add it directly (see the AppendText function) because the event handler is called with a different thread, only the UI thread can update UI components (or you'll get a cross-thread exception).
...
public Form1()
{
InitializeComponent();
getAvailablePorts();
// Subscribe to the DataReceived event. Our function Serial_DataReceived
// will be called whenever there's data available on the serial port.
serial.DataReceived += Serial_DataReceived;
}
// Appends the given text to the given textbox in a way that is cross-thread
// safe. This can be called by any thread, not just the UI thread.
private void AppendText(TextBox textBox, string text)
{
// If Invoke is required, i.e. we're not running on the UI thread, then
// we need to invoke it so that this function gets run again but on the UI
// thread.
if (textBox.InvokeRequired)
{
textBox.BeginInvoke(new Action(() => AppendText(textBox, text)));
}
// We're on the UI thread, we can append the new text.
else
{
textBox.Text += text;
}
}
// Gets called whenever we receive data on the serial port.
private void Serial_DataReceived(object sender,
SerialDataReceivedEventArgs e)
{
string serialData = serial.ReadExisting();
AppendText(textBox5, serialData);
}
Because i want to add an rotating 3D cube i decided to switch to WPF. I heard it is much easier to implement a 3D graphic there. So i copied my code to the new WPF project. But now i got already problems to visualize my values on the Textboxes. It doesnt work. It looks like the Evenhandler did not fire an event while receiving Data from the com port.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data;
using System.Drawing;
namespace cube
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
getAvailablePorts();
serial.DataReceived += Serial_DataReceived;
}
public bool button3clicked = false;
public bool button4clicked = false;
public bool button5clicked = false;
SerialPort serial = new SerialPort();
void getAvailablePorts()
{
List<string> Itemlist = new List<string>();
String[] ports = SerialPort.GetPortNames();
Itemlist.AddRange(ports);
comboBox1.ItemsSource = Itemlist;
}
private void button1_Click_1(object sender, EventArgs e)
{
try
{
if (comboBox1.Text == "" || textBox6.Text == "")
{
MessageBox.Show("Please Select Port Settings");
}
else
{
serial.PortName = comboBox1.Text;
serial.BaudRate = Convert.ToInt32(textBox6.Text);
serial.Parity = Parity.None;
serial.StopBits = StopBits.One;
serial.DataBits = 8;
serial.Handshake = Handshake.None;
serial.Open();
MessageBox.Show("connected!");
}
}
catch (UnauthorizedAccessException)
{
MessageBox.Show("Unauthorised Access");
}
}
private void button2_Click_1(object sender, EventArgs e)
{
textBox1.Clear();
textBox2.Clear();
textBox3.Clear();
textBox4.Clear();
textBox5.Clear();
MessageBox.Show("connection closed!");
serial.Close();
textBox1.Text = "test";
}
private void AppendText(string[] text)
{
try
{
textBox1.Text = text[0];
textBox2.Text = text[1];
textBox3.Text = text[2];
textBox4.Text = text[3];
}
catch (Exception) { }
}
private void Safe_Position1(TextBox tBr1, TextBox tBi1, TextBox tBj1, TextBox tBk1, string[] text)
{
if (button3clicked == true)
{
tBr1.Text = text[0];
tBi1.Text = text[1];
tBj1.Text = text[2];
tBk1.Text = text[3];
button3clicked = false;
}
}
private void Safe_Position2(TextBox tBr2, TextBox tBi2, TextBox tBj2, TextBox tBk2, string[] text)
{
if (button4clicked == true)
{
tBr2.Text = text[0];
tBi2.Text = text[1];
tBj2.Text = text[2];
tBk2.Text = text[3];
button4clicked = false;
}
}
private void Safe_Position3(TextBox tBr3, TextBox tBi3, TextBox tBj3, TextBox tBk3, string[] text)
{
if (button5clicked == true)
{
tBr3.Text = text[0];
tBi3.Text = text[1];
tBj3.Text = text[2];
tBk3.Text = text[3];
button5clicked = false;
}
}
private void Serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string serialData = serial.ReadLine();
String[] text = serialData.Split(new char[] { ' ' });
AppendText(text);
Safe_Position1(textBox5, textBox7, textBox8, textBox9, text);
Safe_Position2(textBox10, textBox11, textBox12, textBox13, text);
Safe_Position3(textBox14, textBox15, textBox16, textBox17, text);
}
private void button3_Click(object sender, EventArgs e)
{
button3clicked = true;
}
private void button4_Click(object sender, EventArgs e)
{
button4clicked = true;
}
private void button5_Click(object sender, EventArgs e)
{
button5clicked = true;
}
}
}
I have an application in Visual studio, reading value from serial port and drawing it on a chart. Everything goes perfecly fine, but when I click a close button on the application (or serial port disconnect button), an error occurs:"IOException() was unhandled", and the program highlights the serial1.Readline() command. How can I handle the exception?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Windows.Forms.DataVisualization.Charting;
namespace usart3
{
public partial class OknoGlowne : Form
{
public OknoGlowne()
{
string[] mojePorty = SerialPort.GetPortNames();
InitializeComponent();
foreach (string port in mojePorty)
{
cmbPorty.Items.Add(port);
}
cmbBaud.Items.Add(2400);
cmbBaud.Items.Add(9600);
cmbBaud.Items.Add(19200);
btnRozlacz.Enabled = false;
}
private volatile string rxString;
//private byte[] rxByte;
private Object thisLock = new Object();
Boolean i = false;
private void btnPolacz_Click(object sender, EventArgs e)
{
i = true;
serialPort1.PortName = cmbPorty.Text;
serialPort1.BaudRate = Convert.ToInt32(cmbBaud.Text);
serialPort1.Parity = Parity.None;
serialPort1.StopBits = StopBits.One;
serialPort1.DataBits = 8;
serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
serialPort1.Open();
btnPolacz.Enabled = false;
btnRozlacz.Enabled = true;
}
int rt = 0;
private void btnRozlacz_Click(object sender, EventArgs e)
{
serialPort1.Close();
btnPolacz.Enabled = true;
btnRozlacz.Enabled = false;
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
rt++;
rxString = serialPort1.ReadLine();
this.Invoke(new EventHandler(displayText));
}
private void displayText(object o, EventArgs e)
{
richTextBox1.AppendText(rxString);
this.chart1.Series["Temperatura"].Points.AddXY(rt, rxString);
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
Form2 nowy = new Form2();
nowy.Show();
}
private void textBox5_TextChanged(object sender, EventArgs e)
{
}
private void Start2_Click(object sender, EventArgs e)
{
Form2 nowy = new Form2();
nowy.Show();
}
private void button1_Click_1(object sender, EventArgs e)
{
Form2 nowy = new Form2();
nowy.Show();
}
}
}
I had similar issue.
The IOExcpection is kind of confusing because accordingly to the documentation ReadLine() is not supposed to throw this type of exception. The problem is that ReadLine is in a state of waiting for an EOL character when we close the port. Closing the port stops the thread holding ReadLine in an unsupported state.
For me the solution was to follow this port closure sequence:
Unsubscribe data_reciver method from the port.
Send a port.WriteLine("get serial number") command. The goal is to trig an EOL character in the input_buffer. This will release ReadLine.
Wait until EOL is recieved.
Close the port.
Surround your call with a try/catch block. In the catch you should code in way that you can handle the error by doing something else.
try {
rxString = serialPort1.ReadLine();
} catch (IOException e) {
// or do something else
}
EDIT:
try {
rt++;
rxString = serialPort1.ReadLine();
this.Invoke(new EventHandler(displayText));
} catch (IOException e) {
MessageBox.Show("Connection is lost");
}
I have a little problem with setting my client-server app for multiple clients usage. I can connect to server and use one client. I modified a little the code to connect via second client, but i don't really know how can i read and send datas to server from second client that are visible also in first client and server. Any ideas/help? Thanks in advance!
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;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace Server_WF
{
public partial class Form1 : Form
{
private TcpClient client;
static List<TcpListener> listeners = new List<TcpListener>();
public StreamReader SR;
public StreamWriter SW;
public string otrzymano;
public String msg;
public Form1()
{
InitializeComponent();
IPAddress[] localIP = Dns.GetHostAddresses(Dns.GetHostName()); // Pobieranie własnego IP
foreach(IPAddress adres in localIP)
{
if (adres.AddressFamily == AddressFamily.InterNetwork)
{
textBox3.Text = adres.ToString();
}
}
}
private void button2_Click(object sender, EventArgs e) // START SERVER
{
TcpListener listener = new TcpListener(IPAddress.Any, int.Parse(textBox4.Text));
listeners.Add(listener);
listener.Start();
client = listener.AcceptTcpClient();
SR = new StreamReader(client.GetStream());
SW = new StreamWriter(client.GetStream());
SW.AutoFlush = true;
backgroundWorker1.RunWorkerAsync(); // Rozpocznij odbieranie danych
backgroundWorker2.WorkerSupportsCancellation = true; // Zdolność do usunięcia wątku
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) // Odbieranie danych
{
while(client.Connected)
{
try
{
otrzymano = SR.ReadLine();
this.textBox2.Invoke(new MethodInvoker(delegate() { textBox2.AppendText("Ktoś: " + otrzymano + "\n"); }));
otrzymano = "";
}
catch(Exception x)
{
MessageBox.Show(x.Message.ToString());
}
}
}
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e) // Przesyłanie danych
{
if(client.Connected)
{
SW.WriteLine(msg);
this.textBox2.Invoke(new MethodInvoker(delegate() { textBox2.AppendText("Ja: " + msg + "\n"); }));
}
else
{
MessageBox.Show("Wysyłanie nie powiodło się.");
}
backgroundWorker2.CancelAsync();
}
private void button3_Click(object sender, EventArgs e) // Połącz z serwerem
{
client = new TcpClient();
IPEndPoint IP_End = new IPEndPoint(IPAddress.Parse(textBox5.Text), int.Parse(textBox6.Text));
try
{
client.Connect(IP_End);
if(client.Connected)
{
textBox2.AppendText("Połączono z serwerem..." + "\n");
SW = new StreamWriter(client.GetStream());
SR = new StreamReader(client.GetStream());
SW.AutoFlush = true;
backgroundWorker1.RunWorkerAsync(); // Rozpocznij odbieranie danych
backgroundWorker2.WorkerSupportsCancellation = true; // Zdolność do usunięcia wątku
}
}
catch(Exception x)
{
MessageBox.Show(x.Message.ToString());
}
}
private void button1_Click(object sender, EventArgs e)
{
if(textBox1.Text != "")
{
msg = textBox1.Text;
backgroundWorker2.RunWorkerAsync();
}
textBox1.Text = "";
}
}
}
Oh dear, there's a lot to do in your code. First of all: don't call CancelAsync from your background worker code. It is not necessary and probably causes problem. Also, a background worker should never ever display MessageBoxes!
Secondly, a background worker is not the right tool in this case!
Thirdly: You need to make your code completely asynchronous. So please look into the BeginAcceptTcpClient. Then, handle each connected client in its own thread (NOT background worker!).
It's probably best you google for examples on how to do this, as this would be far too much to write up here.
I am bascially trying to make a barebones IRC client with C#, WinForms, and TcpClient that will display raw data from the irc server onto the the text area (textbox1). However I am struggling on the updating code (reading the stream from the server). Right now I have a timer that runs a function (listener) that reads from the TCP stream every 100ms. However my application freezes and the cursor disapeears, and the application hangs trying to grab more data. So what would be a better updating function?
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.IO;
using System.Net.Sockets;
namespace LogernIRC
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//Variables
TcpClient client;
StreamReader sr;
StreamWriter sw;
//Functions
public void connect(string host)
{
client = new TcpClient(host, 6667);
sr = new StreamReader(client.GetStream());
sw = new StreamWriter(client.GetStream());
}
public void write(string str)
{
textBox1.Text += str;
}
public void sendData(string str)
{
sw.WriteLine(str);
sw.Flush();
}
public void listener()
{
string data = sr.ReadLine();
write(data);
}
//End Functions
private void Form1_Load(object sender, EventArgs e)
{
//Initialize
write("Welcome to LogernIRC. Type \"/help\" for help with commands.\r\n");
}
private void button1_Click(object sender, EventArgs e) //Submit button clicked
{
//TextBox 1 is the text area , textbox 2 is the message/command area
//Command Area
if (textBox2.Text == "/help")
{
write("Help:\r\n/connect Connect to IRC server\r\n/help Display this help menu\r\n/join Join channel");
}
if (textBox2.Text.StartsWith("/connect"))
{
write("\r\nConnecting to " + textBox2.Text.Split(' ')[1] + " on port 6667...");
connect(textBox2.Text.Split(' ')[1]);
}
if (textBox2.Text.StartsWith("/join"))
{
write("\r\nJoining channel " + textBox2.Text.Split(' ')[1]);
}
if (textBox2.Text == "/test")
{
timer1.Start();
connect("irc.freenode.net");
write("\r\nActivating test function...");
sendData("NICK Logern");
sendData("USER Logern 0 * :LOGERN");
listener();
}
}
private void timer1_Tick(object sender, EventArgs e)
{
//Read Data
listener();
}
}
}
The delay happens when your timer event is raised, but there's no data to read. It will just sit and wait until there is. The best way to address the issue is to use asynchronous operations to handle the I/O. For example:
public Form1()
{
InitializeComponent();
}
//Variables
TcpClient client;
StreamReader sr;
StreamWriter sw;
//Functions
public void connect(string host)
{
client = new TcpClient(host, 6667);
sr = new StreamReader(client.GetStream());
sw = new StreamWriter(client.GetStream());
}
public void write(string str)
{
textBox1.Text += str;
}
public void sendData(string str)
{
sw.WriteLine(str);
sw.Flush();
}
public async Task listener()
{
try
{
string data
while ((data = await sr.ReadLineAsync()) != null)
{
write(data);
}
}
catch (ObjectDisposedException)
{
// socket was closed forcefully
}
}
//End Functions
private void Form1_Load(object sender, EventArgs e)
{
//Initialize
write("Welcome to LogernIRC. Type \"/help\" for help with commands.\r\n");
}
private void button1_Click(object sender, EventArgs e) //Submit button clicked
{
//TextBox 1 is the text area , textbox 2 is the message/command area
//Command Area
if (textBox2.Text == "/help")
{
write("Help:\r\n/connect Connect to IRC server\r\n/help Display this help menu\r\n/join Join channel");
}
if (textBox2.Text.StartsWith("/connect"))
{
write("\r\nConnecting to " + textBox2.Text.Split(' ')[1] + " on port 6667...");
connect(textBox2.Text.Split(' ')[1]);
}
if (textBox2.Text.StartsWith("/join"))
{
write("\r\nJoining channel " + textBox2.Text.Split(' ')[1]);
}
if (textBox2.Text == "/test")
{
connect("irc.freenode.net");
// initiate async reading (storing the returned Task in a variable
// prevents the compiler from complaining that we don't await the
// call).
var _ = listener();
write("\r\nActivating test function...");
sendData("NICK Logern");
sendData("USER Logern 0 * :LOGERN");
}
}
The above example leaves out some error-checking and other niceties, but it's the basic idea of what you want to do.
It's not running async, right? So the UI will lock up until the loop is done. You're looping forever, right? That's pretty common with IRC bots/clients; I've done it myself.
If so, and if you're using NET 4.0 and above, you could try this:
await Task.Run(()=> { CodeThatLoopsForever(); });
Let me try to explain it better. Let's say for example you have a function like this:
private void Connect()
{
while (true)
{
// Do socket listening
}
}
And you call it from clicking a button, like this:
private void btn_Connect_Click(object sender, EventArgs e)
{
Connect();
}
You could just change that button code to this:
private async void btn_Connect_Click(object sender, EventArgs e)
{
await Task.Run(()=> { Connect(); });
}
Hope this helps!
UPDATE: .NET 4.0 and above!