2011-01-11 4 views
1

인터페이스가 고정되어있는 C# .NET 멀티 스레드 응용 프로그램이 있습니다. 이는 특이한 점은 화면 보호기를 시작할 수있을만큼 시스템을 유휴 상태로 두지 않으면 인터페이스가 멈추지 않는다는 것입니다. 시스템을 다시 사용하려면 암호를 다시 입력해야합니다. 인터페이스가 다시 표시되면 (암호를 성공적으로 입력 한 후) 인터페이스가 잠 깁니다. 스크린 세이버를 시작하지 않으면 인터페이스가 잠기지 않습니다.멀티 스레딩 C# 응용 프로그램에서 인터페이스가 멈 춥니 다.

동일한 DLL에 액세스 할 수있는 두 개의 실행 파일이 있으며 DLL에 액세스하는 데 어떤 응용 프로그램을 사용하든이 문제가 발생하고 있음을 지적해야합니다. 이것은 두 응용 프로그램이 DLL과 관련성이있는 것과는 별개로 (C++/MFC)와 (C# /. NET) 완전히 다른 것으로서 DLL에 문제가 있음을 암시하는 것으로 보입니다.

두 exes는 DLL과 상호 작용하는 방식이 비슷한 단계를 수행합니다. DLL을 호출하여 직렬 포트 통신을 설정하고 DLL에서 상태 창을 열고 DLL에서 통신 포트를 모니터링하는 스레드를 시작한 다음 dll에서 스택을 모니터링하는 주 응용 프로그램에서 스레드를 시작합니다.

데이터가 통신 포트에서 DLL의 스레드에 의해 얻어지면 파싱되고 결과가 스택에 배치 된 다음 대리인을 통해 상태 창에 게시됩니다. exe의 스레드가 스택의 데이터를 볼 때 주 창에서 대리자를 사용하여 데이터를 출력합니다.

DLL 내 스레드에 코드를 추가하여 30 초마다 Application.DoEvents()를 호출하면 인터페이스가 약 30 초 동결되어 정상적인 동작을 다시 시작한다는 것을 알게되었습니다. 무언가가 주 스레드를 차단하고 DoEvents()가 강제로 잠금을 해제하는 것으로 보이지만이 잠금을 유발할 수있는 정보가 없습니다.

이 문제는 내 개발 컴퓨터와 테스트 컴퓨터에서 발생합니다.

나는 DLL 내부의 상태 창에 대한 데이터 출력을 완전히 제거하려고 시도했지만 아무런 차이가 없었습니다.

나는 수년간 멀티 스레드 프로그래밍을 해오 고 있으며 이와 같은 것을 본 적이 없다. 그래서 어떤 조언을 크게 주시면 감사하겠습니다.

감사합니다.

+3

디버거에서 고정 된 UI를 일시 중지하고 호출 스택을 봅니다. – SLaks

+0

비 UI 스레드에서만 DLL 메서드를 호출하고 UI 스레드로 마샬링 해 봤니? – RobS

+0

이것은 전체적으로 도움이되지는 않지만 화면 보호기가 작동 할 때 켜지는 절전 기능이 있습니까? (포트가 잠자기 상태가 될 수 있다고 생각합니다.) – vlad259

답변

6

사용자 인터페이스를 초기화하는 데 비표준 방법이있을 때 일반적으로 SystemEvents 클래스에서 유발되는 문제입니다. 쓰레드 사용하기. 프로그램, Debug + Break 모두, Debug + Windows + Threads를 시작하십시오. ".NET SystemEvents"라는 스레드가 있으면이 중단을 보장해야합니다.

일부 배경 : SystemEvent 클래스는 콘솔 모드 앱과 GUI 앱을 모두 지원합니다. 후자의 경우 이벤트 핸들러를 UI 스레드에서 시작해야합니다. 하나의 이벤트가 처음 등록되면 시스템 알림을 얻기 위해 약간의 보이지 않는 도우미 창이 생성됩니다. 이것은 호출 스레드에 창을 작성하거나 보조 스레드를 시작하여 두 가지 방법으로 수행 할 수 있습니다. Thread.GetApartmentState()의 값을 기반으로 결정합니다. STA이면 호출하는 스레드에서 창을 만들 수 있고 모든 이벤트 콜백을 해당 스레드에 적절히 마샬링 할 수 있습니다.

처음 만든 첫 번째 창 창이 UI 스레드에서 생성되지 않으면이 문제가 발생합니다. 예를 들어 스플래시 화면. 이 윈도우는 UserPreferenceChanged와 같은 시스템 이벤트에 관심이있는 컨트롤을 포함 할 수 있으므로 제대로 다시 칠할 수 있습니다. 이제는 도우미 스레드를 사용하며 UI 스레드가 아닌 해당 도우미 스레드에서 발생하는 모든 이벤트가 발생합니다. UI 스레드에서 실행되는 모든 창에 대한 독.잠긴 워크 스테이션 (화면 보호기 포함)에서 세션 스위치가 교착 상태를 일으킬 수있는 신비한 이유가 있습니다. 또한 가끔 그림 그리는 사고가 나올 수도 있는데 잘못된 스레드에서 창을 사용하는 결과가 덜 나 빠지기 때문입니다.

Microsoft.Win32.SystemEvents.UserPreferenceChanged += delegate { }; 
+0

이 DLL을 호출하는 C#/.NET 응용 프로그램에이 작업을 충분히 쉽게 추가 할 수 있지만이 DLL을 호출하는 C++/MFC 응용 프로그램에는 무엇을해야합니까? – PhilGyro

+0

Erm, 초기화 함수를 호출 하시겠습니까? C++ 코드가 스레드 (CoInitializeEx가 STA를 선택하도록)를 올바르게 초기화합니까? init 함수에서 Thread.CurrentThread.GetApartmentState()를 확인하는 것이 좋습니다. –

+0

DLL을 처음 입력 할 때 현재 스레드의 아파트 상태를 확인하고 STA를 설정했습니다. 또한 위의 권장 줄을 Application.Run() 전에 C# exe의 기본 메서드에 추가했지만 아무런 차이가 없었습니다. 내 exe를 시작하면 기본 폼의 창을 열고 사용자가 버튼을 클릭하면 com 포트가 열리고 스레드가 시작되도록 DLL이 호출됩니다. 사용자가 실행할 모드를 선택하면 exe는 DLL로 다시 한 번 호출하여 상태 창을 연 다음 dll의 스레드에 데이터 수집을 시작하라는 경고를 보냅니다. – PhilGyro

0

이 문제는 ActiveX 컨트롤과 관련이있을 것으로 보인다 않습니다 초기화 순서를 고정에서 짧은

는 해결 방법은, 자신의 메인() 메소드에 넣고 어떤 창을 생성 전에이다 아마도 폼에서 잘못 사용했을 수도 있습니다. .NET에서 직렬 포트 라이브러리를 사용하도록 전환했으며 내 문제를 재현하지 못했습니다. 모두에게 감사합니다. 특히 Hans에게 도움을주었습니다.

0

화면 보호기가 시작될 때 내 PC가 멈추거나 PC가 잠겨 모니터가 잠자기 상태가 될 때와 동일한 문제가 발생합니다. 내 멀티 스레드 응용 프로그램에 교착 상태가 나타나는 것을 95 % 확신합니다. 코드에 교착 상태가 있는지 확인하고 확인하십시오.

관련 문제