Thread Exit problem
I am writing a program which receives data from serialport and updates UI elements like textboxe, labels etc. timer is us开发者_如何转开发ed to send command to the device frequently, in response device returns some data that is displayed. Everything is fine. now, in between if I move main form or minimize it then the thread in which receiving code is running exit (as i think). Is it possible that moving main form can cause a thread to be exited ? And what could be the problem in my program? why data receiving stops? posible solution ?
You are updating UI elements in resieving thread.
That means that you have to Invoke UI update call on controls, because they are not created in another thread.
so, I'm guessing that reciever works as follows:
while(!Application.IsApplicationExiting)
{
if (!serial.IsReady) break;
...
Data data = serial.GetData();
string text = GetBaudRate(data);
ui.Invoke((Label label) => label.Text = value, txtBauldRateLabel);
...
}
At the time, you should know that in this case this thread are blocked, until call to UI thread ends, but interesing part is that updates to UI thread also blocks when you try to resize, or position the app window.
Your UI thread blocks when you try to click and hold for a while the right mouse button on a tite bar of your application.
So, you have a lock on a reciever's main cycle that actually shoudn't be blocked in any way in case of timeout on a device, which raises shutdown of a reciever (changes the state of the serial to non-ready).
I advice you to rewrite your app using unblocking call to BeginInvoke():
while(!Application.IsApplicationExiting)
{
...
ui.BeginInvoke((Label label) => label.Text = value, txtBauldRateLabel);
...
}
You behaviors(move/minimize the form) won't affect the threads created in code behind in most circumstances. The data thread updating the UI(maybe use something like myControl.Invoke) will work fine even you are moving the form or minimized the form(but if you close the form without the updating thread aborted, you will get exceptions). So you shouldn't worry about this. Instead I think you need to check the code behind of the moving event or minimized event of your form. Providing some code is helpful to find out the reason.
There is a debugging window called Threads. Start your program and open the threads window when a breakpoint is hit. When your thread is recieving data there should be at least two thread IDs listed, the UI thread and the thread getting and receiving the serial data. You might want to NAME your thread so it will be easier to see in the debugger, otherwise there will just be thread IDs. From there this should give some clues to why or at least when it is exiting.
Put breakpoints in your thread code as well as your UI code to monitor. The question is fairly vague but debugging and watching the threads shoudl help.
You're crashing the timer thread because you're updating the form controls from it directly... you can't do that! You have to call Invoke() so that your code executes from the main UI thread.
I posted an answer in your other question... here it is again:
My guess is that you're crashing your timer thread, because you can't update the Form controls from another thread without issues... you have to create a delegate that runs under the main UI thread. You do this by testing Form.InvokeRequired
and calling Form.Invoke
if it's true.
What's happening: Your timer thread is updating the textboxes or other controls on the form. You resize or minimize, and the handles to those form controls are invalidated... you can't use them anymore. Except your timer thread is still running and trying to use them. Crash!
A good example on multithreaded forms is here. The important part is:
delegate void SetBoolDelegate(bool parameter);
// This would be your timer tick event handler...
void SetInputEnabled(bool enabled) {
if(!InvokeRequired) {
button1.Enabled=enabled;
comboBoxDigits.Enabled=enabled;
numericUpDownDigits.Enabled=enabled;
}
else {
Invoke(new SetBoolDelegate(SetInputEnabled),new object[] {enabled});
}
}
In this example, you test InvokeRequired. If it's false, then you're running on the main UI thread and can set the control properties directly. If it's true, you call Invoke(), passing a function that will be called from the main UI thread.
In this example, the function/delegate you call is the same function you're in, but it doesn't have to be. But you can pass it the timer tick event handler to have that execute on the main thread.
精彩评论