Streamwriter is null even when it has been initialized in C# - c#

I am trying to use sockets to send messages to computers, but I keep getting this error:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
sw was null.
This is my code:
public partial class ServerGUI : Form
{
Socket soc;
StreamReader sr;
StreamWriter sw;
Stream s;
public ServerGUI()
{
InitializeComponent();
try
{
if (Server.port == 0)
{ }
else
{
textBox2.Text = Server.port.ToString();
}
}
catch (Exception) { }
}
private void button1_Click(object sender, EventArgs e)
{
connect();
}
void connect()
{
Server.port = int.Parse(textBox2.Text);
TcpListener listener = new TcpListener(IPAddress.Any, Server.port);
listener.Start();
soc = listener.AcceptSocket();
s = new NetworkStream(soc);
sr = new StreamReader(s);
sw = new StreamWriter(s);
sw.AutoFlush = true; // enable automatic flushing
if (soc.Connected == true)
{
Console.WriteLine("Connected");
sw.WriteLine("Server Connected");
}
this.Hide();
Menu menu = new Menu();
menu.Show();
}
void recieve()
{
Console.WriteLine(sr.ReadLine());
}
public void close()
{
s.Close();
soc.Disconnect(true);
Menu menu = new Menu();
menu.Close();
this.Show();
}
public void send(string msg)
{
sw.WriteLine(msg);
}
This is the code for the button:
ServerGUI sgui = new ServerGUI();
public Menu()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
sgui.close();
}
private void button2_Click(object sender, EventArgs e)
{
sgui.send(textBox1.Text);
}
The writeline code in the connect method works but the code in the send method doesn't. I have tried this question: What is a NullPointerException, and how do I fix it? but it has not helped me.
Thanks

If the send method is called before the connect method the the StreamWriter sw is set to null and a NullReferenceException is thrown inside the send method.
A quick fix is to check the sw property before using it like:
public void send(string msg)
{
if (sw != null)
sw.WriteLine(msg);
}
or with a newer C# language feature a little bit shorter:
public void send(string msg)
{
sw?.WriteLine(msg);
}
EDIT:
The problem is that with the line ServerGUI sgui = new ServerGUI(); you create a new (second) ServerGUI form after hiding the former one that hat its own sw property. This sw property has been never initialized because the created StreamWriter instance is part of the first gui that you just have hidden.
Although this design (strong coupling of forms without a data/service layer) is not ideal, a way to fix this is to pass the form instance to the Menu. E.g.
var menu = new Menu();
menu.ServerGui = this;
menu.Show();
and of course the Menu class has to introduce a ServerGUI property like public
class Menu {
...
public ServerGUI ServerGui {get; set;}
private void button1_Click(object sender, EventArgs e)
{
ServerGui.close();
}
private void button2_Click(object sender, EventArgs e)
{
ServerGui.send(textBox1.Text);
}

Related

Automatically auto-check every new item in a checkedboxlist in c#

I am trying to auto check every new item in my checkedboxlist I have a button that does that it will auto select all, but we don't want it that way to be controlled by a button. we want it so for every new item we get automatically will get checked.
This is my button that auto select all if there are new 20 items this will auto select all and then submit those new items
Here is the code it works but is not I want I want to auto select for every new items coming in, because I have another process that will keep adding new items to the checkedboxlist, also the lst_BarcodeScanEvents is the checkedboxlist name
private void btn_SelectALLScans_Click(object sender, EventArgs e)
{
for (var i = 0; i < lst_BarcodeScanEvents.Items.Count; i++)
{
lst_BarcodeScanEvents.SetItemChecked(i, true);
}
}
I checked other sources like google and stackoverflow but I could not find anything to my request here.
Here is the main class where I have the logic of buttons, checkedlistbox and more. and the button method btn_ConnectT_Click calls the methods from the second class
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.Web;
using BarcodeReceivingApp.Core.Domain;
using BarcodeReceivingApp.Functionality;
namespace BarcodeReceivingApp
{
public partial class BarcodeReceivingForm : Form
{
//GLOBAL VARIABLES
private const string Hostname = "myip";
private const int Port = 23;
private TelnetConnection _connection;
private ParseReceivingBarcode _parseReceivingBarcode;
private ButtonsDisplay _buttonsDisplay;
public BarcodeReceivingForm()
{
InitializeComponent();
//FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
}
private void btn_ConnectT_Click(object sender, EventArgs e)
{
_connection = new TelnetConnection(Hostname, Port);
_connection.ServerSocket(Hostname, Port, this);
}
private void btn_StopConnection_Click(object sender, EventArgs e)
{
_connection.Exit();
}
private void btn_RemoveItemFromListAt_Click(object sender, EventArgs e)
{
if (lst_BarcodeScanEvents.CheckedItems.Count != 0)
for (var i = lst_BarcodeScanEvents.CheckedItems.Count; i > 0; i--)
lst_BarcodeScanEvents.Items.RemoveAt(lst_BarcodeScanEvents.CheckedIndices[i - 1]);
else
MessageBox.Show(#"Element(s) Not Selected...");
}
private void BarcodeReceivingForm_Load(object sender, EventArgs e)
{
_buttonsDisplay = new ButtonsDisplay(this);
_buttonsDisplay.ButtonDisplay();
}
private void btn_ApplicationSettings_Click(object sender, EventArgs e)
{
var bcSettingsForm = new BarcodeReceivingSettingsForm();
bcSettingsForm.Show();
}
private void btn_ClearBarcodeList_Click(object sender, EventArgs e)
{
lst_BarcodeScanEvents.Items.Clear();
}
private void lst_BarcodeScanEvents_ItemAdded(object sender, ListBoxItemEventArgs e)
{
MessageBox.Show(#"Item was added at index " + e.Index + #" and the value is " + lst_BarcodeScanEvents.Items[e.Index].ToString());
}
private void btn_SubmitData_Click(object sender, EventArgs e)
{
var receivingFullBarcode = new List<string>();
_connection.GetBarcodeList();
}
private void btn_SelectALLScans_Click(object sender, EventArgs e)
{
for (var i = 0; i < lst_BarcodeScanEvents.Items.Count; i++)
{
lst_BarcodeScanEvents.SetItemChecked(i, true);
}
}
}
}
Here is the second class where I use a telnet port 23 that scan barcodes where and puts it to the checkedlistbox, now the main emethods here that inserts the data to the checkedlistbox is the method serversocket and the readwrite method
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace BarcodeReceivingApp.Functionality
{
public class TelnetConnection
{
private Thread _readWriteThread;
private TcpClient _client;
private NetworkStream _networkStream;
private string _hostname;
private int _port;
private BarcodeReceivingForm _form;
private bool _isExiting = false;
public TelnetConnection(string hostname, int port)
{
this._hostname = hostname;
this._port = port;
}
public void ServerSocket(string ip, int port, BarcodeReceivingForm f)
{
this._form = f;
try
{
_client = new TcpClient(ip, port);
}
catch (SocketException)
{
MessageBox.Show(#"Failed to connect to server");
return;
}
_networkStream = _client.GetStream();
_readWriteThread = new Thread(ReadWrite);
//_readWriteThread = new Thread(() => ReadWrite(f));
_readWriteThread.Start();
}
public void Exit()
{
_isExiting = true;
}
public void ReadWrite()
{
do
{
var received = Read();
if (received == null)
break;
if (_form.lst_BarcodeScanEvents.InvokeRequired)
{
var received1 = received;
_form.lst_BarcodeScanEvents.Invoke(new MethodInvoker(delegate
{
_form.lst_BarcodeScanEvents.AddItem(received1 + Environment.NewLine);
}));
}
} while (!_isExiting);
//var material = received.Substring(10, 5);
//_form.label5.Text += string.Join(Environment.NewLine, material);
CloseConnection();
}
public List<string> GetBarcodeList()
{
var readData = new List<string>();
foreach (string list in _form.lst_BarcodeScanEvents.Items)
{
readData.Add(list);
MessageBox.Show(list);
}
return readData;
}
public string Read()
{
var data = new byte[1024];
var received = "";
var size = _networkStream.Read(data, 0, data.Length);
if (size == 0)
return null;
received = Encoding.ASCII.GetString(data, 0, size);
return received;
}
public void CloseConnection()
{
MessageBox.Show(#"Closed Connection",#"Important Message");
_networkStream.Close();
_client.Close();
}
}
}
so now like I said before for every new items it gets inserted to the checkedlistbox I want it to be auto selected everytime it adds a new data to the checkedlistbox.
The problem, usually simple, of setting the Checked state of a newly added Item of a CheckedListBox, was somewhat complicated because of the nature of the Listbox in question.
The CheckedListBox is a Custom Control with custom events and properties.
It's actually a relatively common customization (one implementation can be see in this MSDN Forum post:
Have ListBox an event when addid or removing Items?) but it might complicate the interpretation of the events.
The Custom Control, when adding a new Item to the List (from a class other than the Form that hosts the Control), raises the custom ItemAdded event
private void [CheckedListBox]_ItemAdded(object sender, ListBoxItemEventArgs e)
The Index of the Item added is referenced by the e.Index property of the custom ListBoxItemEventArgs object.
With the code provided, it can be determined that this event handler is the natural place where the Checked state of the new Item can be set:
private void lst_BarcodeScanEvents_ItemAdded(object sender, ListBoxItemEventArgs e)
{
lst_BarcodeScanEvents.SetItemChecked(e.Index, true);
}
For that I suggest to create an event that you subscribe after you InitializeComponent() of your form like so :
public Form1()
{
InitializeComponent();
lst_BarcodeScanEvents.ControlAdded += new ControlEventHandler(AddedNewSelect);
}
private void AddedNewSelect(object sender, ControlEventArgs e)
{
lst_BarcodeScanEvents.SetItemChecked(e.Control.TabIndex, true);
}

C#: DataReceived Event handler for serialPort not firing

I'm writing a fairly basic application, where one of the tasks is communicating with an Arduino Uno card.
I would like to write the serial communication as a separate module, so the forms only calls for the input from Arduino, and the module will handle the creating and opening of the serialPort and reading data from it.
For testing purposes I wrote a program for the Arduino which prints the elapsed milliseconds every half second to the serialPort.
I would like to populate the textBox of my Form with the output from Arduino after I press a button.
I create the serialPort in the SerialComm class, and although I attach a DataReceived event handler to it, it never seems to fire.
Here is the code for the SerialComm class:
class SerialComm
{
private List<String> availablePorts;
private SerialPort arduino;
private string receivedText;
public String[] portList
{ get
{
EnumPorts();
return availablePorts.ToArray();
}
}
public string receivedData
{
get
{
return receivedText;
}
}
public void InitialiseSerial()
{
arduino = new SerialPort();
arduino.BaudRate = 9600;
arduino.DtrEnable = true;
// Add event handler
arduino.DataReceived += new SerialDataReceivedEventHandler(arduino_DataReceived);
}
public void EnumPorts()
{
availablePorts = new List<string>();
foreach (string s in SerialPort.GetPortNames())
{
availablePorts.Add(s);
}
}
public void StartMC(SerialPort serialPort, String portName)
{
arduino = serialPort;
if (arduino.IsOpen)
{
arduino.Close();
}
else
{
//Initialise Serial Port
arduino.PortName = portName;
arduino.Open();
}
}
//This never fires==================
private void arduino_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
receivedText = arduino.ReadExisting();
}
public void CloseMC()
{
if (arduino.IsOpen)
{
arduino.Close();
arduino.Dispose();
}
}
}
In the Form I call the text from Arduino like this: (I have a button (Button1), a combobox for selecting the COM port (comboBox1) and a textBox on the Form)
public partial class Form1 : Form
{
SerialComm arduino = new SerialComm();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//Arduino
arduino.InitialiseSerial();
String[] portList = arduino.portList;
foreach (String COM in portList)
{
comboBox1.Items.Add(COM);
}
if (portList.Length > 0)
{
comboBox1.SelectedItem = comboBox1.Items[0];
}
else
{
comboBox1.Text = "No microcontroller found!";
}
}
private void button1_Click(object sender, EventArgs e)
{
arduino.StartMC(serialPort1, comboBox1.SelectedItem.ToString());
//as the DataReceived never fires arduino.receivedData stays null
if (arduino.receivedData != null)
{
for (int i = 0; i < 101; i++)
{
textBox1.AppendText(arduino.receivedData);
}
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
arduino.CloseMC();
}
}
Do you see any reason why the event handler doesn't trigger?
Thank you very much for your help in advance.
Best Regards,
Peter

Changing a single client server into a multiple server c#

Okay so I have ran into a problem, I have created a server which handles a single client and now I want to kick it up a notch and have it handle multiple clients at one time.
I have looked and tried to do this using HashTables and also Async but I keep getting stuck, this is a grey area for me as I have only just recently started dealing with sockets etc...
I wondered if anyone had a way of doing it?
Any advise will be taken on board.
This is my server code(If it helps).
namespace ChatServer
{
delegate void UpdateTextBox(string msg);
public partial class Form1 : Form
{
private TcpListener ConnectionListener;
private BinaryReader MessageReader;
private BinaryWriter MessageWriter;
private Socket ClientConnection;
private NetworkStream DataStream;
private Thread ListeningThread;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
try
{
IPAddress.Parse(textBox3.Text);//
ListeningThread = new Thread(new ThreadStart(ListenForConnections));
ListeningThread.Start();
}
catch (Exception)
{
MessageBox.Show("Wrong Ip Address");
}
}
private void button2_Click(object sender, EventArgs e)
{
try
{
if (ClientConnection.Connected)
{
MessageWriter.Write(textBox2.Text);
textBox2.Clear();
}
}
catch (Exception)
{
MessageBox.Show("no client is connected");
}
}
private void textBox2_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
try
{
if (ClientConnection.Connected)
{
MessageWriter.Write(textBox2.Text);
textBox2.Clear();
}
}
catch (Exception)
{
MessageBox.Show("no client is connected");
}
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
System.Environment.Exit(System.Environment.ExitCode);
}
private void ListenForConnections()
{
try
{
ConnectionListener = new TcpListener(IPAddress.Parse(textBox3.Text), 80);
ConnectionListener.Start();
ChangeTextBoxContent("Listening For Connections");
ClientConnection = ConnectionListener.AcceptSocket();
DataStream = new NetworkStream(ClientConnection);
MessageReader = new BinaryReader(DataStream);
MessageWriter = new BinaryWriter(DataStream);
ChangeTextBoxContent("Connection Received");
HandleConnection();
MessageReader.Close();
MessageWriter.Close();
DataStream.Close();
ClientConnection.Close();
}
catch (Exception)
{
MessageBox.Show("Unable to connect, wrong ip address");
}
}
private void HandleConnection()
{
string message;
do
{
try
{
message = MessageReader.ReadString();
ChangeTextBoxContent(message);
}
catch (Exception)
{
ChangeTextBoxContent("connection Lost");
break;
}
} while (true);
}
private void ChangeTextBoxContent(string tx)
{
if (textBox1.InvokeRequired)
{
Invoke(new UpdateTextBox(ChangeTextBoxContent), new object[] { tx });
}
else
{
textBox1.Text += tx + "\r\n";
}
}
}
}
Thank you in advance.
You should handle each of your connections in a separate thread. Create a loop that constantly listens for remote connections, and when a remote connection is called, create a new thread with the connection as the object parameter.

Handle serial thread event in WPF GUI class

I have a serial port class, and I would like to control send/receive via my GUI, and have the GUI update based on receipt of data from the serial port (or other events). So the two relevant classes are the serial class and the main window class.
I have the code below which compiles, but I get an exception when I try to run.
public class MySerThread
{
public SerialPort serport;
public event SerialDataReceivedEventHandler newSerData;
public MySerThread()
{
serport = new SerialPort("COM1", 115200);
serport.Open();
serport.DataReceived += DataReceivedHandler;
}
public void DataReceivedHandler(object s, SerialDataReceivedEventArgs e)
{
byte[] data = new byte[serport.BytesToRead];
serport.Read(data, 0, data.Length);
// here's where I think I'm going wrong?
if(newSerData != null)
newSerData(s,e);
}
}
And then in my GUI class...
public partial class MainWindow : Window
{
MySerThread myPort;
public MainWindow()
{
// Exception triggers here
myPort.newSerData += DisplaySerDataHandler;
}
private void DisplaySerDataHandler(object sender, SerialDataReceivedEventArgs e)
{
this.ReceivedCallback(e);
}
private void ReceivedCallback(SerialDataReceivedEventArgs e)
{
if(this.someTextBlock.Dispatcher.CheckAccess())
{
this.UpdateTextBlock(e);
}
else
{
this.someTextBlock.Dispatcher.BeginInvoke(new Action<SerialDataReceivedEventArgs>(this.UpdateTextBlock), e);
}
}
private void UpdateTextBlock(SerialDataReceivedEventArgs e)
{
someTextBlock.Text = "got new data";
}
}
So, what am I doing wrong here? What is the best way to do this?
You can't access myPort without creating an instance.
MySerThread myPort = new MySerThread();

Listening to text/event-stream using C#

I am writing a C# class to wrap around a simple web service. The RESTful stuff was easy to wrap up, but now I need to raise an event when something on the server changes.
I've set the server up to make an event stream available, but I don't know how to pick up the stream in C#.
Currently I'm dong something like this:
public class ServiceWrapper
{
private readonly wc = new WebClient();
public ServiceWrapper()
{
wc.OpenReadAsync(new Uri(UriOfEvent));
wc.OpenReadCompleted += ServerEventOccurs;
}
private void ServerEventOccurs(object sender, OpenReadCompletedEventArgs args)
{
using (var sr = new StreamReader(args.Result))
{
var message = ParseStream(sr);
RaiseServerEventOccurred(message);
}
wc.OpenReadAsync(new Uri(UriOfEvent));
}
//usual code for declaring and raising ServerEventOccurred event
}
In my test the event gets picked up once, but not twice. The event on the server is essentially a switch - something happens and it goes on, something else happens and it goes off. I know the switching works, because I've hooked the event stream up to a normal web page to test it.
How should I be dealing with event streams in C#?
Edit 1: I've updated the code to fix the bug TimVK points out, but the event stream still isn't being picked up the second time it should be.
Doesn't it work when you put your wc as a property in the class instead of creating always a new one in your methods?
public class ServiceWrapper
{
WebClient wc {get;set;}
public ServiceWrapper()
{
wc = new WebClient();
wc.OpenReadAsync(new Uri(UriOfEvent));
wc.OpenReadCompleted += ServerEventOccurs;
}
private void ServerEventOccurs(object sender, OpenReadCompletedEventArgs args)
{
using (var sr = new StreamReader(args.Result))
{
var message = ParseStream(sr);
RaiseServerEventOccurred(message);
}
wc = new WebClient();
wc.OpenReadAsync(new Uri(UriOfEvent));
}
//usual code for declaring and raising ServerEventOccurred event
}
Then I suppose the event should be raised everytime.
namespace WindowsFormsApp3
{
public partial class Form1 : Form
{
WebClient myWebRequest = null;
String Path = "http://192.168.196.106/home/events/";
Uri uri = null;
public Form1()
{
InitializeComponent();
uri = new Uri(Path);
this.myWebRequest = new WebClient();
this.myWebRequest.Headers.Set("Host", "192.168.196.106");
this.myWebRequest.OpenReadCompleted += MyWebRequest_OpenReadCompleted;
}
private async void MyWebRequest_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
using (var sr = new StreamReader(e.Result))
{
try
{
while (true)
{
var message = await sr.ReadLineAsync();
Debug.WriteLine("message = {0}", (object)message);
}
}
catch (WebException ex)
{
Debug.WriteLine("WebException: {0}", (object)ex.Message);
}
catch (IOException ex)
{
Debug.WriteLine("IOException: {0}", (object)ex.Message);
}
catch (Exception ex)
{
Debug.WriteLine("Exception: {0}", (object)ex.Message);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
myWebRequest.OpenReadAsync(uri);
}
private void button2_Click(object sender, EventArgs e)
{
myWebRequest.CancelAsync();
}
}

Categories

Resources