2011-01-14 6 views
0

serialport에서 데이터를 수신하고 textboxe, label 등과 같은 UI 요소를 업데이트하는 프로그램을 작성 중입니다. 타이머는 장치에 명령을 자주 보내는 데 사용되며 응답 장치는 표시되는 일부 데이터를 반환합니다. 모든 것이 좋습니다. 지금, 중간 폼을 옮기거나 그 다음에 코드를받는 스레드가 최소화되어 있다면 중간에 (내가 생각한 것처럼) exit가 실행됩니다. 메인 폼을 움직이면 스레드가 종료 될 수 있습니까? 그리고 내 프로그램의 문제점은 무엇입니까? 데이터 수신이 중단되는 이유는 무엇입니까? 가능한 해결책?스레드 종료 문제

+2

코드를 게시하지 않았습니다. 그것은 내가 당신을 도울 수없는 동일한 이유입니다 (이 질문을 한 마지막 시간) (http://stackoverflow.com/questions/4667272/receiving-data-from-serialport-stops-when-main-form-is- 최소화 또는 이동). –

+1

코드 개요를 게시 할 수 있습니까? –

답변

0

대부분의 상황에서 비헤이비어 (양식 이동/최소화)는 코드에서 생성 된 스레드에 영향을주지 않습니다. UI를 업데이트하는 데이터 스레드 (myControl.Invoke와 같은 것을 사용할 수도 있음)는 양식을 이동하거나 양식을 최소화하더라도 제대로 작동합니다 (그러나 업데이트 스레드를 중단하지 않고 양식을 닫으면 예외가 발생합니다). 그래서 이것에 대해 걱정할 필요가 없습니다. 대신 나는 당신이 움직이는 이벤트의 코드를 확인하거나 폼의 이벤트를 최소화 할 필요가 있다고 생각합니다. 몇 가지 코드를 제공하면 이유를 찾는 데 도움이됩니다.

0

Threads라는 디버깅 창이 있습니다. 중단 점에 도달하면 프로그램을 시작하고 스레드 창을 엽니 다. 쓰레드가 데이터를 수신 할 때 적어도 두 개의 쓰레드 ID, UI 쓰레드, 직렬 데이터를 얻고받는 쓰레드가 있어야한다. 스레드 이름을 NAME으로 지정하여 디버거에서보기 쉽게 할 수 있습니다. 그렇지 않으면 스레드 ID 만있을 것입니다. 거기에서 이것은 왜 또는 적어도 나가는 지에 대한 단서를 제공해야합니다.

모니터 할 UI 코드와 스레드 코드에 중단 점을 넣으십시오. 질문은 상당히 모호하지만 디버깅과 스레드 shoudl 도움을보고.

1

스레드 검색 중 UI 요소를 업데이트하고 있습니다.

즉, 다른 스레드에서 만들어지지 않았기 때문에 컨트롤에서 UI 업데이트 호출을 호출해야합니다.

그래서, 나는 다음과 같이 그 리시버가 작동 같은데요 : UI 스레드 종료를 호출 할 때까지,

while(!Application.IsApplicationExiting) 
{ 
    if (!serial.IsReady) break; 
    ... 
    Data data = serial.GetData(); 
    string text = GetBaudRate(data); 
    ui.Invoke((Label label) => label.Text = value, txtBauldRateLabel); 
    ... 
} 

,이 스레드가 차단이 경우 알고해야하지만, 일부는 interesing UI 스레드의 업데이트는 크기를 조정하거나 앱 창을 배치하려고 할 때 차단됩니다.

응용 프로그램의 tite bar에서 마우스 오른쪽 버튼을 잠시 누르고 있으면 UI 스레드가 차단됩니다.

장치의 시간 초과로 인해 실제로 차단되지 않을 수신자의 주주기가 잠겨있어 수신자가 종료됩니다 (직렬 상태가 준비되지 않음으로 변경됨).).

I 조언 당신은 BeginInvoke()에 차단 해제 전화를 사용하여 응용 프로그램을 다시 작성하기 : 당신이 직접에서 양식 컨트롤을 업데이트하고 있기 때문에 당신은 타이머 스레드를 충돌하고

while(!Application.IsApplicationExiting) 
{ 
    ... 
    ui.BeginInvoke((Label label) => label.Text = value, txtBauldRateLabel); 
    ... 
} 
0

을 ... 당신이 할 수있는 ' 그럴 수 없어! 코드가 기본 UI 스레드에서 실행되도록 Invoke()를 호출해야합니다. 당신이 당신의 타이머 스레드를 충돌하고 있다는


내 생각은, 다른에서 양식 컨트롤을 업데이트 할 수 없기 때문에 :

내가 여기 다시는 ... 다른 질문에 대한 답변을 게시 스레드가 문제없이 ... 기본 UI 스레드에서 실행되는 대리자를 만들어야합니다. Form.InvokeRequired을 테스트하고 Form.Invoke을 호출하여이 작업을 수행합니다.

변경 사항 : 타이머 스레드가 양식의 텍스트 상자 또는 다른 컨트롤을 업데이트하고 있습니다. 크기를 조정하거나 최소화하면 해당 양식 컨트롤의 핸들이 무효화되므로 더 이상 사용할 수 없습니다. 타이머 스레드가 여전히 실행 중이며이를 사용하려고 시도하는 것을 제외하고는. 추락!

멀티 스레드 형식의 좋은 예는 here입니다. 중요한 부분은 다음과 같습니다.

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}); 
    } 

} 

이 예제에서는 InvokeRequired를 테스트합니다. false 인 경우 기본 UI 스레드에서 실행 중이며 컨트롤 속성을 직접 설정할 수 있습니다. 사실이라면 Invoke()를 호출하여 기본 UI 스레드에서 호출 할 함수를 전달합니다.

이 예제에서 사용자가 호출하는 함수/위임자는 현재 가지고있는 함수와 동일하지만 반드시 그렇게 할 필요는 없습니다. 하지만 타이머 틱 이벤트 핸들러를 전달하여 메인 스레드에서 실행되도록 할 수 있습니다.