I am fairly new to multi threading, therefore please excuse any obvious mistakes which may be present - I am still learning!
I currently have a program which reads in from a port using TCPClient
and NetworkStream
and outputs the data to a text box
in a WPF program. Nonetheless, when trying to read in multiple times from the stream
, it slows the program down quite noticeably and the more it has to read, the longer it takes for the program to open. Therefore I decided to try and implement threading
and I am trying to use Background Worker
.
Here is the code I have in the MainWindow
:
InitializeComponent();
try
{
client.Connect(address, port); //connect to the client
nwStream = client.GetStream(); //read in data from stream
readInTxtBox.Text = ("Connection Open");
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync();
}
catch (SocketException ex)
{
readInTxtBox.Text = ex.ToString(); //write out the error
}
finally
{
client.Close();
}
This is the worker_DoWork
and worker_RunWorkerCompleted
methods:
void worker_DoWork(object sender, DoWorkEventArgs e)
{
if (Dispatcher.CheckAccess())
{
ReadIn();
}
else
{
Dispatcher.BeginInvoke(new Action(() =>
{
ReadIn();
}));
}
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Dispatcher.BeginInvoke(new Action(() =>
{
OutputToTextBoxInput();
}));
}
When stepping through, it does go to the Dispatcher.BeginInvoke
action on the worker_DoWork
, and fails on the first line of the ReadIn()
method :
private void ReadIn()
{
byte[] b = Utilities.ReadInBytes(client, nwStream); //fails here!
hex = Utilities.ConvertByteToHex(b);
nwStream.Close();
}
It fails
on the following line of the ReadInBytes
method, with the error: Cannot access a disposed object.
public static byte[] ReadInBytes(TcpClient client, NetworkStream nwStream)
{
byte[] bytesToRead = new byte[client.ReceiveBufferSize]; //FAILS HERE
int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
ArraySegment<byte> segment = new ArraySegment<byte>(bytesToRead, 0, bytesRead);
return segment.ToArray();
}
The client
and network stream
are declared as public statics
. I have had this problem when using invoke
and when not. I have also tried BeginInvoke
and the same problem has occurred.
Any help would be massively appreciated as well as any explanations on where I have gone wrong!
The problem is, that you dispose the client in the finally block, but use it in the DoWork
methods which is running later.
To solve it, create, connect and clode the client in the DoWork event :).
As mentioned in a comment, you should not dispatch your code in the DoWork method! Just call ReadIn there. You want to run the code in background, so that the GUI remains resposable - it makes no sense to push it to the GUI thread!
It is also not required to dispatch the code in the RunWorkerCompleted event handler, because the background work does it for you ;).