ContextSwitchDeadlock이 C #에서 오류를 감지했습니다.


80

C # 응용 프로그램을 실행 중이며 런타임 중에 다음 오류가 발생합니다.

CLR이 60 초 동안 COM 컨텍스트 0x20e480에서 COM 컨텍스트 0x20e5f0으로 전환 할 수 없습니다. 대상 컨텍스트 / 아파트를 소유하는 스레드는 비 펌핑 대기를 수행하거나 Windows 메시지를 펌핑하지 않고 매우 오래 실행되는 작업을 처리 할 가능성이 높습니다. 이 상황은 일반적으로 성능에 부정적인 영향을 미치며 애플리케이션이 응답하지 않거나 시간이 지남에 따라 메모리 사용량이 지속적으로 누적 될 수 있습니다. 이 문제를 방지하려면 모든 STA (단일 스레드 아파트) 스레드에서 펌핑 대기 기본 형식 (예 : CoWaitForMultipleHandles)을 사용하고 장기 실행 작업 중에 메시지를 정기적으로 펌프해야합니다.

누구든지 여기서 문제를 해결할 수 있습니까?

감사합니다.

답변:


123

프로그램의 메인 스레드가 1 분 동안 코드를 실행하는 데 바빴습니다. 정상적인 업무를 처리하지 않고 메시지 루프를 펌핑합니다. 작업자 스레드에서 COM 서버를 사용할 때는 불법입니다. 주 스레드가 다시 유휴 상태가 될 때까지 해당 메서드에 대한 호출을 전달할 수 없습니다.

쉽게 볼 수 있어야하며 UI는 문 못처럼 죽어야합니다. Windows는 "응답하지 않음"을 표시하는 고스트로 기본 창을 대체해야합니다. 창을 닫아도 작동하지 않으며 클릭 이벤트가 적용되지 않습니다.

메인 스레드가 수행하는 작업은 작업자 스레드가 대신 수행해야합니다. 이 BackgroundWorker클래스는 이에 적합하며 MSDN Library 문서에서 많은 사용 도움말을 찾을 수 있습니다. 메인 스레드가 무엇을하는지 모르는 경우 Debug + Break All, Debug + Windows + Threads를 사용하세요.

한 가지 더 가능한 원인 : RTM 버전의 VS2005를 사용하는 경우 서비스 팩 1을 설치해야합니다.


5
+1은 이러한 작업 항목을 보조 스레드로 이동해야 함을 설명하므로이 오류를 방지하는 방법에 대한 솔루션입니다 (오류를 생성하는 이유가 아님).
JYelton

2
다른 몇 가지 사내 구축 응용 프로그램이 내 것보다 훨씬 더 오래 중단되는 것을 보았는데 흥미롭게도이 오류 메시지가 표시됩니다. hmmm.
Coops


1
자세한 설명을 보내 주셔서 감사합니다. 제가 사용한 해결 방법은 비동기 함수이며 이제는 완벽합니다. 따라서 내가 수집 한 내용에서 특히 COM을 사용할 때 장기 실행 작업을 위해 새 스레드를 관리하는 것이 매우 중요합니다.
Anthony Mason

50

컨텍스트 전환을 차단하고 contextSwitchDeadlock MDA 를 표시 하는 작업을 찾으려면 다음 단계를 사용할 수 있습니다. Visual Studio 2012를 참조 할 것입니다.

  1. 오류를 재현하십시오. 이것은 시행 착오를 수반 할 수 있습니다.
  2. 표시되는 Managed Debugging Assistant에서 'Continue'대신 'OK'를 클릭합니다.
  3. 도구 모음 도킹 영역을 마우스 오른쪽 버튼으로 클릭하고 '디버그 위치'를 선택하여 디버그 위치 도구 모음이 활성화되었는지 확인합니다. 도구 모음에 '스레드'라고 표시된 드롭 다운 목록이 활성화되어 있어야합니다.
  4. 스레드 드롭 다운 목록에서 선택한 항목은 기본 스레드가 모든 관심을 끌고 있다고 불평하는 백그라운드 스레드이므로 기본 스레드가 아닌 스레드 여야합니다. 드롭 다운 목록에서 메인 스레드를 선택합니다.
  5. 이제 코드 편집기에서 컨텍스트 전환을 차단하는 코드를 볼 수 있습니다.

리소스 집약적 인 작업을 기본 스레드에서 이동하지 않기로 결정했다고 가정하고, 수행하기 전에 여기에서 다른 답변과 주석을 살펴보십시오. 관리 형 디버깅 도우미를 비활성화하는 다음 옵션이 있습니다.

Visual Studio 디버거 내

  1. 'Break when this exception type is thrown'의 선택을 취소하여 오류 발생시 표시되는 MDA 대화 상자에서 MDA를 직접 비활성화 할 수 있습니다.
  2. 아래의 MSDN 지침을 사용하여 예외 설정 대화 상자로 .

... 디버그 메뉴에서 예외를 클릭합니다. (디버그 메뉴에 예외 명령이 포함되어 있지 않으면 도구 메뉴에서 사용자 지정을 클릭하여 추가합니다.) 예외 대화 상자에서 관리되는 디버깅 도우미 목록을 확장 한 다음 개별 MDA에 대한 throw 확인란의 선택을 취소합니다.

Visual Studio 디버거 외부

  1. 레지스트리 키 (시스템 전체, 영향을받는 모든 MDA)
  2. 환경 변수 (Machine Wide, MDA 지정 가능)
  3. 애플리케이션 구성 설정 (애플리케이션 범위, MDA를 지정할 수 있음)

참고 : 세 번째 옵션이 적용 되려면 처음 두 옵션 중 하나를 1로 설정해야합니다.

필자의 경우 문제는 콘솔 응용 프로그램 내의 Entity Framework에서 ObjectContext.SaveChanges () 에 대한 호출이었습니다 . 으로 MTAThreadAttribute가 받는 적용 Main()방법 ContextSwitchDeadlock 예외는 더 이상 제기되지 않았다 . 안타깝게도이 변경 사항이 미치는 영향을 잘 모르겠습니다.


2
프로세스를 차단하는 코드를 찾는 방법에 대한 명확한 설명에 찬성 투표하십시오.
Guillaume Schuermans 2013-06-26

10

이 메시지는 일부 코드가 스레드 전환을 시도하고 있으며 대상 스레드가 사용 중임을 나타냅니다. 예를 들어, UI가 한동안 타이트한 루프를 실행하는 동안 UI 스레드에 호출을 전달하여 UI를 업데이트하려는 백그라운드 스레드가 있습니다.

실제로 무슨 일이 일어나고 있는지 알아 내려면 디버거에 침입하여 모든 스레드와 이들이 수행하는 작업을 살펴 ​​봐야합니다.


4

일부 경우 :
디버그-> 예외-> 관리되는 디버그 도우미
및 ContextSwitchDeadlock 항목 선택 취소.


5
예,하지만 일회성 테스트를 작성할 때 방해가되는 경우 비활성화 할 수있는 것이 좋습니다.
Tod

4
아뇨. 이것은 문제에 대한 해결책이 아닙니다.
Tom W

3
과학자가 아닌 엔지니어처럼 생각해야합니다 !!
Ehsan Zargar Ershadi

4
@Ehsan Ershadi, 좋은 엔지니어는 문제를 예측하고 해결하는 것이 아니라 문제를 해결합니다.
Mo Patel 2013

4
LOL. 오류를보고 싶지 않다면 모니터가 아닌 다른 곳을 볼 수 있습니다. 이것은 "솔루션"과 동일한 접근 방식입니다. 이것은 해결책이 아닙니다. 이것은 단지 무시하는 것입니다!
curiousBoy

0

Visual Studio 2005 창의 디버그 메뉴, Edxception 대화 상자의 팝업에서 예외를 선택하고 Managed Debugging Assistants Exception Node를 선택한 다음 ContextSwitchDeadlock을 선택하고 Thrown 열에서 선택을 제거하면됩니다. 이것은 vs가 ContextSwitchDeadlock 예외를 던지는 것을 막을 것입니다.

도움이 되었기를 바랍니다..


60
팔에 불이 붙어 있습니다. 단순히 칼을 사용하여 뇌에 통증을 전달하는 신경을 절단하십시오. 이렇게하면 팔에 불이 붙었다는 것을 알 수 없습니다.
Ozzah

어쨌든 이것은 일시적으로 문제를 해결하는 방법입니다. 이 문제를 완전히 차단하려면 응용 프로그램 디자인에 대해 재고 할 시간이 필요합니다.
왕 Jijun

0

OracleDataReader예외를 던지는 이유를 알아 내려고 할 때이 문제 가 발생했습니다. null예외가`null 인 매개 변수와 관련 되어 있기 때문에 할당 되었기 때문이라고 생각했습니다 . 그래서 나는 :

while (dr.Read())
{
    while (dr != null)  // <-- added this line
    {
      ...

(가) 밝혀졌다 dr널 결코 루프 그래서 그냥 당신이 메모리가 부족할 때까지 (이렇게하지 계속하기에 당신이 클릭 할 수 있기 때문에 좀 더 "계속"에이 메시지가 도착할 때까지과에 가서 - 대신 "확인"을 클릭하십시오.) 이야기의 도덕적 인 점은 데이터베이스의 데이터를 무한 루프로 메모리로 스트리밍하는 메모리 누수를 찾으십시오. 이 오류는 실제로 잘못된 시나리오를 경고하려는 것입니다. 주의를 기울이는 것이 가장 좋습니다.


0

이 오류는 여러 번 나에게 발생했으며에서 반복을 추적 DataGridViewRow하여 확인란 값을 true로 설정했습니다. 디버그 모드에서 실행하고 있었기 때문에 계속할 수있는 옵션이있어서이 작업을 수행 할 수있었습니다.

누군가에게 도움이되기를 바랍니다.


0

Visual Studio를 사용한다고 가정하면 Ctrl+Alt+E현재 프로젝트를 클릭 하면 "ContextSwitchDeadlock"옵션의 선택을 취소해야하는 Managed Debugging Assistants 선택과 함께 예외 창이 표시됩니다. 그런 다음 현재 프로젝트를 빌드하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.