Hello,
I am developing a software which communicates over the CAN network. It
has a thread to transmit and another to receive the messages. After
sending some messages the transmit thread holds till it receives a
response from the network. Also the messages trans/received have to be
displayed on the GUI in real time.
For holding the transmit thread, I am using AutoResetEvent.Wait()
When the response is received I am using AutoResetEvent.Set()
For Displaying the messages in real time i am using Virtual ListView
for updating the GUI.
Now the transmit thread sometimes does not recognise that a message is
received, even when the AutoResetEvent is Set.
I think the problem is due to processing of Display and the processing
of AutoResetEvent. I think both the messages for display and autorest
are put in the message queue of the OS, which will process them
sequentially. If the display takes more time to update then the
processing of autoresetevent will take more time.
Is there any solution to this problem?
I think i need to look ahead at two fronts
1. Either change the way i update the GUI with the messages, so that i
may have to change to something other than Virtual ListView
2. Or Find some other way to unblock the transmit thread when i
receive the message.
To provide a code sample which will generate the problem in question
is not possible.
Reason: There are two different things happening for the application,
which the OS is handling.
1: The OS is handling updation of Virtual ListView
2: The Os is handling informing the waiting thread about the event.
The above two things are distributed across various functions, code
listing which will constitute the complete project code. For testing
purpose, I had tried with simple value types like Strings, but that
didnt produce the error. Only when i am using the CAN objects for
display update, i face the problem.
So, at present i believe we first need to theoretically solve the
problem, and then maybe get onto the code.
For added information about the code:
1. The receive thread raises the autoresetevent and also makes a
boolean variable true. This way when the transmit thread is waiting,
it can either get the boolean variable to be true or the event.
2. The boolean variable is declared as static volatile
So the question is
1. While the OS is busy updating the virtual listview, it cannot
process any other event. Is there any method force the OS to use the
thread pool for the display update, and continue catering to the
events raised.
2. Is there any other way other than a) raising an event & b) boolean
variable to communicate between the threads about the state of the
network response.
3. Or should there be some other control be used for displaying the
messages, i.e instead of using Virtual Listview, some other things
cvan be used?
SpaceMan
Comments
The first issue is that it sounds like you are accessing UI elements from outside the UI thread. Now I'm not familiar with the virtual list view but if it is a UI element then it must be worked with on the UI thread. The way you do this is to use the "Invoke" method on either it or another UI element.
[code]
MyListView.Invoke(
new MethodInvoker(
delegate
{
// Whatever code you need to do to the UI here.
}));
[/code]
The UI thread actually works off of a queue - and this will insert your delegate into that queue, so as soon as the UI thread has a chance it will execute the code you wanted. This call will wait for UI thread execution before returning as well so you don't need to worry about any multi threading issues.
Which brings me to the other issue it sounds like you might be having somewhere. If you are using multiple threads you should ensure that you are locking them properly when accessing shared data. the lock() command will do this for you.
Basically what you have to do is have an object to which all of your threads have access to use as the lock focus. Even if it's just a dummy object. Then - any time you are accessing shared information you must enter a lock that will tell all other threads to wait until you finish your access and they will all take turns.
This is sometimes thought as one of the most tricky parts of windows programming to deal with because if you don't use your locks properly you can cause bottlenecks and threadlocking (i.e. two threads are waiting on each other and they never exit causing your threads to freeze)
so for a quick example:
[code]
var threadlock = new object();
var result = "";
var t1 = new Thread(
new ParameterizedThreadStart(
delegate
{
lock (threadlock)
for (int i = 0; i < 10; i++)
result += "From Thread 1
";
}));
var t2 = new Thread(
new ParameterizedThreadStart(
delegate
{
lock (threadlock)
for (int i = 0; i < 10; i++)
result += "From Thread 2
";
}));
t1.Start();
t2.Start();
while (t2.ThreadState == System.Threading.ThreadState.Running || t2.ThreadState == System.Threading.ThreadState.Running)
Thread.Sleep(0);
lock (threadlock)
MessageBox.Show(result);
[/code]
So here you will see all of the thread1 messages before the thread 2 messages.
the thread focus is just an object that "lock" will use to determine if other locks need to wait for.
So if you have to totally seperate threading issues going on, you could use 2 different object for lock focus and the locks using each focus would never wait for each other.
><//~Psightoplasm`~