Invoke function still trow an exception for cross thread operation - c#

I find a simple example for collecting information from an industrial equipment via MTConnect standard and adapted to my equipment. The example received periodically, via network, a variable lenght text buffer and display in a listbox. I modify the original code to display meaningfull information by searching and parsing the received buffer to be display in textbox and progress bar.The receiving function, running on an event, is the following:
public void OnRecievedData( IAsyncResult ar )
{
Socket sock = (Socket)ar.AsyncState;
// Check if any data was received
try
{
int nBytesRec = sock.EndReceive( ar );
if( nBytesRec > 0 )
{
// Add the data to the List
string sRecieved = Encoding.ASCII.GetString( m_byBuff, 0, nBytesRec );
//sRecieved = Encoding.ASCII.GetString(m_byBuff, 0, nBytesRec);
// WARNING : The following line is NOT thread safe. Invoke is
// m_lbRecievedData.Items.Add( sRecieved );
//Invoke( m_AddMessage, new string [] { sRecieved } );
Invoke(myDelegate, sRecieved);
// If the connection is still usable restablish the callback
SetupRecieveCallback( sock );
}
else
{
// If no data was recieved then the connection is probably dead
Console.WriteLine( "Client {0}, disconnected", sock.RemoteEndPoint );
sock.Shutdown( SocketShutdown.Both );
sock.Close();
}
}
catch( Exception ex )
{
MessageBox.Show( this, ex.Message, "Unknown error on Recieve!" );
}
}
m_AddMessage process the RX buffer and fill in the most simpler example just m_lbRecieveData list box while in my code the buffer is first parse then the interesting data display in variuos text box.
As seen in commented lines, I try to use Invoke directly on m_AddMessage function then in the latest try using a delegate. The code run correctly for a variable length of time then trow an exception :
Cross-thread operation not valid: FormMain accessed from a thread
other than the thread it was created on
No helpfull information on which thread raised the exception are available. I search any info related to the problem (include this forum) and follow several example on using Invoke but I always obtain the same result. I really appreciate any help on resolving this issue

Related

c# Message Message Queue Count. - Sharing violation resulted from queue being open already for exclusive receive

So I am busy writing an Watchdog for message queue installed on one of my servers. I have a application ( 3rd party ) that is listening on the queue and processing the messages. I now want to do a count on it and if message reach example 1500 I send a email. So all my code works except that I need to close the 3rd party app to use the message queue. What I do is I get all the queue names that exist. Work fine.
public void GetPrivateQueues()
{
MessageQueue[] QueueList =
MessageQueue.GetPrivateQueuesByMachine(".");
foreach (MessageQueue queueItem in QueueList)
{
i++;
myPrivateQueues.Add(queueItem.Path);
Count(queueItem.Path);
}
return;
}
So when I do the count of the queue like this
public void Count(String path)
{
MessageQueue queue = new MessageQueue(path);
MessageEnumerator messageEnumerator = queue.GetMessageEnumerator2();
int iii = 0;
while (messageEnumerator.MoveNext())
{
iii++;
}
myPrivateQueuesCount.Add(iii);
return;//i;
}
I get the error.
System.Messaging.MessageQueueException (0x80004005): Sharing violation resulted from queue being open already for exclusive receive.
How can I go about reading the queue to do a count without trying to get exclusive access on it. I just need to count it.
Thank you
Regards
I used performance Counter to read the queue.
Working like a dream now!
Added the catch exception. This is for when the queue is blank. I write a 0. Performance counter gives error on blank queue.
public void Count(String path)
{
path = path.Remove(0, 21);
try
{
PerformanceCounter queueCounter = new PerformanceCounter(
"MSMQ Queue",
"Messages in Queue",
#path);
Console.WriteLine("Queue contains {0} messages",
queueCounter.NextValue().ToString());
myPrivateQueuesCount.Add((int)queueCounter.NextValue());
}
catch (Exception exc)
{
myPrivateQueuesCount.Add(0);
}
return;
}

Socket tcp c# how to clear input buffer?

I'm writing an application for windows phone and I need to communicate with a server and transmit data. The SERVER is written in C++ and I cannot modify it. The CLIENT is what I have to write. The Server is designed such that the client connect to it and transmit data. The connection remains open for all the transmission. By writing my code in C# I am able to receive data from the server but after the first receive, the data that I read in the buffer are alway the same. So I need a way to flush the input buffer so I can receive the new data (data are sent continuously). I'm using the class defined in here:
http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202858%28v=vs.105%29.aspx
thanks a lot !!
I used this code for Receiving in the SocketClient.cs :
public string Receive()
{
string response = "Operation Timeout";
// We are receiving over an established socket connection
if (_socket != null)
{
// Create SocketAsyncEventArgs context object
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
socketEventArg.RemoteEndPoint = _socket.RemoteEndPoint;
// Setup the buffer to receive the data
socketEventArg.SetBuffer(new Byte[MAX_BUFFER_SIZE], 0, MAX_BUFFER_SIZE);
// Inline event handler for the Completed event.
// Note: This even handler was implemented inline in order to make
// this method self-contained.
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
// *********************************************
// THIS part of the code was added to receive
// a vector of 3 double
Double[] OdomD = new Double[3];
for (int i = 0; i < 3; i++)
{
OdomD[i] = BitConverter.ToDouble(e.Buffer, 8 * i);
}
// *********************************************
}
else
{
response = e.SocketError.ToString();
}
_clientDone.Set();
});
// Sets the state of the event to nonsignaled, causing threads to block
_clientDone.Reset();
// Make an asynchronous Receive request over the socket
_socket.ReceiveAsync(socketEventArg);
// Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds.
// If no response comes back within this time then proceed
_clientDone.WaitOne(TIMEOUT_MILLISECONDS);
}
else
{
response = "Socket is not initialized";
}
return response;
}
The Connect() method is exactly the same reported in the link above. So when the application start, the Connect() method is called as follow:
SocketClient client = new SocketClient();
// Attempt to connect to server for receiving data
Log(String.Format("Connecting to server '{0}' over port {1} (data) ...", txtRemoteHost.Text, 4444), true);
result = client.Connect(txtRemoteHost.Text, 4444);
Log(result, false);
That is done just once at the beginning, then I need receive this array of 3 double that is updated every second. So I use:
Log("Requesting Receive ...", true);
result = client.Receive();
Log(result, false);
The problem is that also if I debug the code and stop the execution inside Receive(), I always read the same value, that is the first value sent by the server. What I'm expecting is that every time I call client.Receive(), I get the new value, but this is not appening.
I had a similar problem by writing the same client in Matlab environment. I solved the problem by using the function flushinput(t) before to read the input buffer. In this way I was able to read always the last data sent by the server. I'm lookin for a function similar to that one ..
The size of the input buffer is fixed equal to the data that I'm expecting to receive, in that case is 24 bytes ( 3* sizeof(double) ) ..
Thanks a lot for you time !!
oleksii is right, you should call client.Receive() in a loop. You can choose to start a thread that covers the receive section of your code. Also note that client.Receive() will keep trying to receive from the buffer, and it will get stuck if there is no data available.
The main question was **how to clear the input buffer? ** or am I wrong?=!
Nevertheless; since you don't have a fixed buffer denoted as seen from you posted code and receive it via the SocketAsyncEventArgs, you could clear it with:
Array.Clear(e.Buffer, 0, e.Buffer.Length);

Exception doesn't be thrown to parent function

I use VS2012 for my project, I am handling the Socket exception when server cannot send message to target machine but It occurs that when It cannot send msg (I already put it in trycatch) Debugger just break in catch block and say the error without send forward to parent catch block. Please tell me, if I did something wrong.
private void sendMessageToTarget(string Message, IPAddress targetAddress, int port)
{
TcpClient client = new TcpClient();
IPEndPoint server = new IPEndPoint(targetAddress, OUT_MESSAGE_PORT);
Thread senderThread = new Thread(new ThreadStart(delegate()
{
try
{
client.Connect(server);
MemoryStream memstream = new MemoryStream();
NetworkStream netstream = client.GetStream();
byte[] sentString = Encoding.ASCII.GetBytes(Message);
netstream.Write(sentString, 0, sentString.Length);
memstream.Close();
netstream.Close();
client.Close();
}
catch (SocketException ex)
{
throw;
}
}));
senderThread.Start();
} // Sending Message Method
Above is my code for sending message to target
try
{
sendMessageToTarget("CONN_CHECKER", target, OUT_MESSAGE_PORT);
}
catch (Exception se)
{
ConnectedUsers.Remove(target.ToString());
UpdateConnectedUserToTeacher();
if (NeedFollowStudents.Contains(target.ToString()))
{
NeedFollowStudents.Remove(target.ToString());
}
UserLostConnection(this, new EventArgs());
}
And this is the method in another function that I want the action to be performed.
There is no magical marshalling exceptions from one thread to another. It is even almost guaranteed that code after senderThread.Start(); will be executed before code in the thread's delegate.
You function that you pass to Thread constructor becomes top level function on a new thread. If such function throws exception (like you do) this exception will go to AppDomain.UnhandledException event and than normally terminates application.
Your options
revert to synchronous code (all code on one thread)
use existing asynchrnous methods that will notify your code about end of operation. Depending on approach notification can be either via event (similar to WebClient.DownloadStringAsync ) or via callback and calling EndXXXXX like Socket.BeginSend
use async
manually implement synchronization and marshalling exception to original thread.
Note that only synchronous version of the code will work the way you want, all other that use multiple threads will not be able to return exception to the same "parent function" (using async will at least allow your code look the way you want even if it will not work the same way).
This is just a guess, but I believe you should only put a Try/Catch in the parent function and not in the child. When the exception occurs it will show in the parent method. The way you have it written will catch the exception in the child method and it will not get passed back to your parent method.

How to make the thread wait for specific seconds

I have a function(please see code below) which reads some data from the web. The problem with this function is that sometimes it will return fast but another time it will wait indefinitely. I heard that threads helps me to wait for a definite period of time and return.
Can you please tell me how to make a thread wait for 'x' seconds and return if there is no activity recorded. My function also returns a string as a result, Is it possible to catch that value while using a thread?
private string ReadMessage(SslStream sslStream)
{
// Read the message sent by the server.
// The end of the message is signaled using the
// "<EOF>" marker.
byte[] buffer = new byte[2048];
StringBuilder messageData = new StringBuilder();
int bytes = -1;
try
{
bytes = sslStream.Read(buffer, 0, buffer.Length);
// Use Decoder class to convert from bytes to UTF8
// in case a character spans two buffers.
Decoder decoder = Encoding.ASCII.GetDecoder();
char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
decoder.GetChars(buffer, 0, bytes, chars, 0);
messageData.Append(chars);
// Check for EOF.
}
catch (Exception ex)
{
throw;
}
return messageData.ToString();
}
For Andre Calil's comment:
My need is to read/write some value to a SSL server. For every write operation the server sends some response, The ReadMessage is responsible for reading the incoming message. I've found situations wnen the ReadMessage(sslStream.Read(buffer, 0, buffer.Length);) waits forever. To combat this problem, i considered threads which can wait for 'x' seconds and return after that. Following code demonstrates the working of ReadMEssage
byte[] messsage = Encoding.UTF8.GetBytes(inputmsg);
// Send hello message to the server.
sslStream.Write(messsage);
sslStream.Flush();
// Read message from the server.
outputmsg = ReadMessage(sslStream);
// Console.WriteLine("Server says: {0}", serverMessage);
// Close the client connection.
client.Close();
You can't (sanely) make a second thread interrupt the one you're executing this code from. Use a read timeout instead:
private string ReadMessage(SslStream sslStream)
{
// set a timeout here or when creating the stream
sslStream.ReadTimeout = 20*1000;
// …
try
{
bytes = sslStream.Read(…);
}
catch (IOException)
{
// a timeout occurred, handle it
}
}
As an aside, the following construct is pointless:
try
{
// some code
}
catch (Exception ex) {
throw;
}
If all you're doing is rethrowing, you don't need the try..catch block at all.
You can set the ReadTimeout on the SslStream so that the call to Read will timeout after a specified amount of time.
If you don't want to block the main thread, use an asynchronous pattern.
Without knowing exactly what you are trying to achieve, it sounds like you want to read data from an SSL stream that may take quite a while to respond, without blocking your UI/main thread.
You can consider doing your read asynchronously instead using BeginRead
Using that approach, you define a callback method that is invoked every time Read has read data and placed it into the specified buffer.
Just sleeping (whether using Thread.Sleep or by setting ReadTimeout on the SslStream) will block the thread this code is running on.
Design it to be Asynchronous by putting the ReadMessage in its own thread waiting for the answer. Once the answer is provided create an event back to the main code to handle its output.

Cross-thread operation not valid

I keep getting the following error when debugging.
Cross-thread operation not valid: Control 'richTextBoxReceivedMsg' accessed from a thread other than the thread it was created on.
Here's the code that it points to:
public void OnDataReceived(IAsyncResult asyn)
{
try
{
SocketPacket socketData = (SocketPacket)asyn.AsyncState;
int iRx = 0;
// Complete the BeginReceive() asynchronous call by EndReceive() method
// which will return the number of characters written to the stream by the client
iRx = socketData.m_currentSocket.EndReceive (asyn);
char[] chars = new char[iRx + 1];
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(socketData.dataBuffer, 0, iRx, chars, 0);
System.String szData = new System.String(chars);
richTextBoxReceivedMsg.AppendText(szData);
// Continue the waiting for data on the Socket
WaitForData( socketData.m_currentSocket);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0,"1","\nOnDataReceived: Socket has been closed\n");
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
Can somebody please help me fix this?
You need to replace this:
richTextBoxReceivedMsg.AppendText(szData);
with something like
Invoke(new Action(() => richTextBoxReceivedMsg.AppendText(szData)));
The reason is that Windows Forms is not really designed to work across different threads. Invoke method will run the delegate you pass to it in the UI thread. If you want to manipulate UI elements via other threads, you'll have to run the actual manipulation on the UI thread. InvokeRequired property will tell you when you need to use Invoke rather than calling the method directly.
check by writing the given statement in your form1() constructor RichTextBox.CheckForIllegalCrossThreadCalls = false;
Thank u....

Categories

Resources