can anyone help me or advice me
I am making an application whereby actions are done according to what is read from networkstream. considering that my application is quite big, i wanna reduce threads and one that i see can be reduced is the thread for scanning of data available in the networkstream. what i am thinking of is somekind of eventhandler whereby if there's a networkstream.dataAvailable then it will execute. here's what i did,
private void OtherCode()
{
thread = new Thread(new ThreadStart(wait_for_commands));
thread.Start();
thread.Priority = ThreadPriority.Normal;
}
protected void wait_for_commands()
{
while (!StopMyThreads)
{
if (MyProgramState == MyProgram_state.idle)
{
if (Base1Connected)
{
if (MyNetworkStream1.DataAvailable)
{
check_opcode();
}
}
}
Application.DoEvents();
}
}
I have no idea on how to make an event handler, hence to make the eventhandler which handles available data on networkstream. can anyone help me

networkstream eventhandler
Jehan Badshah
The reason your code is consuming 100% CPU is because, as I said in my previous post, BeginRead will return immediately.
So your loop will just go round and round again calling BeginRead as fast as it can.
You need to change two things.
First, you don't need to create that new thread any more - there's no need for an extra thread because BeginRead doesn't block. You can call that from your UI thread, and because it returns immediately - it won't cause your UI to freeze. And when the read is complete, it will call your ReadComplete message on a thread pool thread. The thread pool will dynamically adjust the number of threads it has to match the work you are doing.
Second, don't use a loop. Instead, inside your ReadComplete, call BeginRead again after calling EndRead. (Or more safely, do it after you've processed the data: that way you can guarantee that you won't start trying to process incoming data from a single socket on two threads at once!) So your ReadComplete will look something like this:
private void ReadComplete(IAsyncResult iar)
{
byte[] buffer = (byte[])iar.AsyncState;
int BytesAvailable = BaseNetworkStream.EndRead(iar);
//My data process
BaseNetworkStream.BeginRead(buffer, 0, buffer.Length, ReadComplete, buffer);
}
Logically speaking you've still got a kind of loop here - once you've finished processing one buffer of incoming data, you iterate onto the next one. But you're no longer using a C# loop construct to do that. (Mainly because C# loop constructs are designed to work within a single thread, but you're using asynchronous mechanisms that can span multiple threads.)
And finally, setting CheckForIllegalCrossThreadCalls to false is a VERY BAD IDEA! Don't do that. Using Windows Forms controls from the wrong thread is illegal, which is why they called that variable what they did! The only reason you can disable the check at all is that in V1 of .NET, they didn't actually check that calls were on the right thread. (It was still illegal to do cross-thread calls into a control in V1. It's just that it used not to tell you that you'd made a mistake - instead, your application would be prone to deadlocks and random crashes.)
Instead, if you need to make updates to the UI, but your code is on the wrong thread (e.g. a thread pool thread), you should use the Control.BeginInvoke in order to run code back on the UI thread, from where it is safe to update the UI.
This is an unfortunate but necessary aspect of multithreaded programming in Windows Forms. Basically, anything slow (e.g. waiting for data from a network stream) should not happen on the UI thread. But anything you do the UI must happen on the UI thread. So you end up having to write code to shuffle control back and forth between the two threads any time the result of a network stream read needs to have some impact on the UI...
Deedhun
first of, thank you for the prompt reply IanG
after testing the code above, i found that my program is consuming greater CPU process.. almost 100 percent of my CPU is used for the thread that i use for this begin read method. here's the code that i am using now...
private void StartThread()
{
ReceivingThread =
new Thread(new ThreadStart(ReceiveMessage));ReceivingThread.Name =
"Receiving Message Thread";ReceivingThread.Start();
}
private void ReceiveMessage(){
while (!StopMyThread){
byte[] buffer = new byte[32]; try{
BaseNetworkStream.BeginRead(buffer, 0, buffer.Length, ReadComplete, buffer);
}
catch (ObjectDisposedException){
return;}
finally{
}
}
}
private void ReadComplete(IAsyncResult iar){
byte[] buffer = (byte[])iar.AsyncState; int BytesAvailable = BaseNetworkStream.EndRead(iar); //My data process}
And also, do you think its wise to if i use
CheckForIllegalCrossThreadCalls =
false;Thank you,
Dhika
shift244
Dear IanG,
Wow man, I have tried your snippet and it works really well.. not only my program worked well, it also really flexible.. And also I didnt use illegalcrossthreadcheck, I dont know what it will do, but it looks dangerous..
Once Again, Thank you very much
r_daneel
I would recommend 2 things.
First would be to increase the size of your buffer.
The second would be to not put the begin read inside a loop, but at the end of processing your data, or after you have made a copy of the buffer.
Jamie Thomson
The NetworkStream class doesn't raise any events. However, it is possible to achieve what you want to achieve.
The trick is to use the BeginRead method. You do something like this:
void StartRead()
{
byte[] buffer = new byte[4096];
myNetworkStream.BeginRead(buffer, 0, buffer.Length, ReadComplete, buffer);
}
void ReadComplete(IAsyncResult iar)
{
byte[] buffer = (byte[])iar.AsyncState;
int bytesAvailable = myNetworkStream.EndRead(iar);
... process data ...
}
The call to BeginRead returns immediately. It will not consume any threads until data is available. (The documentation suggests otherwise. It is wrong, and it's easy to prove. You can have literally thousands of connections open, all of them with BeginRead operations in progress, and all with just a handful of threads.)
When data becomes available, the NetworkStream will get hold of a thread from the CLR thread pool, and will use that to notify you. In this case it'll call our ReadComplete method. (Because that's what we asked BeginRead to call when data was available.) In this method, we then call EndRead to find out how much data was available, and we can then go ahead and process the data.
The nice thing about this is that your code only uses threads when there is data to be processed. If your application is sat idle waiting for data to come in, it doesn't need a thread for each connection.
The one thing to be wary of is that the ReadComplete method will be called on a CLR thread pool thread. This means you need to be careful about using fields in your object - you might be accessing them from multiple threads at once. You also need to make sure you don't hold onto the thread. The correct programming style is to handle the data as quickly as possible and then return. (If your ReadComplete method is slow to return, this can choke the rate at which your program can handle data. So don't do anything that might block for seconds.)
Also, if this is a GUI application, remember that you won't be able to do anything to the UI in your ReadComplete method because you'll be on a thread pool thread.