Monday 26 February 2018

대기 시간이 멈 춥니 다


대기 시간 정지
App Store를 통해 가져 오기 우리의 응용 프로그램 에서이 게시물을 읽으십시오!
Process. WaitForExit는 Process. HasExited가 true 인 경우에도 반환되지 않습니다.
Process. Start를 사용하여 배치 파일을 시작합니다. 배치 파일은 "START"명령을 사용하여 여러 프로그램을 병렬로 시작한 다음 종료합니다.
일단 배치 파일이 완료되면 Process. HasExited가 true가되고 Process. ExitCode에 올바른 종료 코드가 포함됩니다.
하지만 Process. WaitForExit ()을 호출하면 중단되거나 반환되지 않습니다.
다음 코드는 문제를 보여줍니다. 배치 파일을 만들고 시작한 다음 인쇄합니다.
다음을 인쇄해야합니다.
. 하지만 결코하지 않습니다 (HasExited가 true이고 이미 ExitCode가 있음에도 불구하고).
배치 파일에 "START"명령이 들어있을 때와 표준 출력 및 / 또는 표준 오류가 리디렉션 될 때만 발생하는 것으로 나타났습니다.
WaitForExit ()이 반환하지 않는 이유는 무엇입니까?
그러한 프로세스가 종료 될 때까지 기다리는 올바른 방법은 무엇입니까?
Process. HasExited를 폴링하는 것이 안전합니까? 아니면 다른 문제가 발생할 수 있습니까?
추신 : 나는 방금 WaitForExit (100000)을 거대한 시간 초과 (확실히 만료되지 않음)로 호출하면 프로세스가 종료 될 때 즉시 반환하는 것으로 나타났습니다. 위어드. 타임 아웃이 없으면 중단됩니다.
이것은 표준 오류 및 StandardError의 이벤트 기반 비동기 처리의 특정 구현에서 아티팩트 ( "버그"라고 말합니다) 인 것 같습니다.
나는 당신이 제공 한 코드 (훌륭한 코드 예제, 그런데! :)를 실행함으로써 문제를 쉽게 재현 할 수 있었지만, 프로세스는 실제로 무한정 멈추지 않았다는 것을 알았다. 오히려 WaitForExit ()에서 리턴 된 것은 시작된 두 개의 하위 프로세스가 모두 종료 한 후에였습니다.
이것은 Process 클래스 구현의 의도적 인 부분 인 것으로 보인다. 특히 Process. WaitForExit () 메서드에서 프로세스 핸들 자체에 대한 대기가 끝나면 stdout 또는 stderr에 대한 판독기가 만들어 졌는지 확인합니다. 그렇다면 WaitForExit () 호출의 제한 시간 값이 "무한"(즉, -1)이면 코드는 실제로 리더에서 스트림의 끝을 기다립니다.
각각의 독자는 BeginOutputReadLine () 또는 BeginErrorReadLine () 메서드가 호출 될 때만 만들어집니다. stdout 및 stderr 스트림 자체는 자식 프로세스가 닫힐 때까지 닫히지 않습니다. 그래서 그 흐름이 끝날 때까지 그 흐름이 끝날 때까지 기다리게됩니다.
WaitForExit ()은 스트림의 이벤트 기반 읽기를 시작하는 메소드를 호출했는지 여부에 따라 다르게 동작해야하며 특히 해당 스트림을 직접 읽는 것으로 WaitForExit ()이 그런 식으로 동작하지 않으면 API를 이해하고 사용하기가 훨씬 어려워지는 불일치. 나는 이것을 개인적으로 버그라고 부르지 만, Process 클래스의 구현자가이 불일치를 인식하고 그것을 의도적으로 만들었을 가능성이 있다고 생각한다.
어쨌든, 임시 해결책은 API의 이벤트 기반 부분을 사용하는 대신 StandardOutput 및 StandardError를 직접 읽는 것입니다. 물론 코드가 해당 스트림에서 대기하는 경우에도 자식 프로세스가 종료 될 때까지 동일한 차단 동작이 표시됩니다.
예를 들어 (C #은 코드 예제를 이와 같이 빨리 때리기에 충분할만큼 F #을 알지 못하기 때문에) :) :
위의 해결 방법이나 이와 유사한 방법으로 기본 문제를 해결할 수 있기를 바랍니다. Niels Vorgaard Christensen이 WaitForExit () 메서드의 문제가있는 줄로 안내해 주신 데 대해 감사 드려서이 답변을 개선 할 수있었습니다.

사용 예제.
나는이 방법으로 그것을 해결했다.
나는 입력, 출력 및 오류 모두를 리디렉션하고 출력 및 오류 스트림에서 읽기를 처리했습니다. 이 솔루션은 Windows 7과 Windows 8 모두 SDK 7 - 8.1에서 작동합니다.
Mark Beers, Rob, stevejay 대답을 고려하여 비동기 스트림 읽기를 사용하여 문제를 해결할 클래스를 만들려고했습니다. 그렇게하면 비동기 프로세스 출력 스트림 읽기와 관련된 버그가 있음을 알았습니다.
당신은 그렇게 할 수 없습니다 :
System. InvalidOperationException이 발생합니다 : StandardOut가 리디렉션되지 않았거나 프로세스가 아직 시작되지 않았습니다.
그런 다음 프로세스가 시작된 후 비동기 출력 읽기를 시작해야합니다.
이렇게하면 출력 스트림이 비동기로 설정되기 전에 데이터를받을 수 있기 때문에 경쟁 조건을 만듭니다.
그렇다면 어떤 사람들은 스트림을 비동기로 설정하기 전에 스트림을 읽어야한다고 말할 수 있습니다. 그러나 같은 문제가 발생합니다. 동기 읽기 사이에 경쟁 조건이 있으며 스트림을 비동기 모드로 설정합니다.
"Process"와 "ProcessStartInfo"가 설계된 실제 방식으로 프로세스의 출력 스트림을 안전하게 비동기 적으로 읽는 방법은 없습니다.
다른 사용자가 제안한 것과 같이 비동기 읽기를 사용하는 것이 좋습니다. 그러나 경쟁 조건으로 인해 정보가 누락 될 수 있음을 알고 있어야합니다.
위의 답변 중 하나도 해당 작업을 수행하지 않습니다.
롭 솔루션이 중단되고 'Mark Byers'솔루션이 폐기 된 예외를 얻습니다. (다른 답변의 "솔루션"을 시도했습니다.)
그래서 나는 또 다른 해결책을 제안하기로 결정했다.
이 코드는 디버깅되어 완벽하게 작동합니다.
이것이 간단하고 더 나은 접근 방법입니다 (우리는 AutoResetEvent가 필요 없습니다) :
나는 같은 문제가 있었지만 그 이유는 다르다. 그러나 Windows 8에서는 발생하지만 Windows 7에서는 발생하지 않습니다. 다음 줄이 문제를 일으킨 것으로 보입니다.
해결책은 UseShellExecute를 비활성화하지 않는 것입니다. 원하지 않는 쉘 팝업 창을 받았지만 특별한 일이 일어나지 않을 때까지 기다리는 프로그램보다 훨씬 낫습니다. 그래서 다음과 같은 해결 방법을 추가했습니다.
이제 나를 귀찮게하는 것은 Windows 8에서 왜 이런 일이 일어나고 있는지입니다.
소개.
현재 허용되는 응답이 작동하지 않고 (예외가 throw 됨) 해결 방법이 너무 많지만 완전한 코드가 없습니다. 이것이 대중적인 질문이기 때문에 많은 사람들의 시간을 낭비하는 것은 분명합니다.
Mark Byers의 대답과 Karol Tyl의 대답을 결합하여 Process. Start 메서드를 사용하는 방법을 기반으로 전체 코드를 작성했습니다.
git 명령을 통해 진행 대화 상자를 만드는 데 사용했습니다. 이것이 내가 그것을 사용한 방법입니다 :
이론적으로 stdout과 stderr를 결합 할 수도 있지만 테스트하지는 않았습니다.
나는 이것이 늙다는 것을 알고 있지만이 전체 페이지를 읽은 후에는 해결할 수있는 코드가 없기 때문에 무하마드 레 한 (Muhammad Rehan)을 시도하지는 않았다. . 그것이 완전히 진실하지 않은 경우 작동하지 않는다고 말할 때 가끔은 잘 작동 할 것입니다. EOF 마크 전에 출력의 길이와 관련이 있다고 생각합니다.
어쨌든, 나를 위해 일한 솔루션은 다른 스레드를 사용하여 StandardOutput 및 StandardError를 읽고 메시지를 작성하는 것이 었습니다.
희망이 사람을 도울 수 있기를 바랍니다, 누가 그렇게 열심히 수 있다고 생각!
내부 타임 아웃과 생성 된 애플리케이션에 의한 StandardOutput 및 StandardError의 사용으로 인해 다른 솔루션 (EM0를 포함하여)은 여전히 ​​내 애플리케이션에 대해 교착 상태입니다. 여기 나를 위해 일한 것입니다 :
편집 : StartInfo의 초기화를 코드 샘플에 추가했습니다.
이 게시물 어쩌면 구식하지만 난 왜 그것이 일반적으로 끊어지는 주된 원인은 redirectStandardoutput에 대한 스택 오버 플로우 때문이거나 redirectStandarderror가있는 경우입니다.
출력 데이터 또는 오류 데이터가 크기 때문에 무한정 지속되는 동안 정지 시간이 발생합니다.

대기 시간 정지
내 응용 프로그램에 다음 코드가 있습니다.
System. Diagnostics. Process proc = new System. Diagnostics. Process ();
다른 응용 프로그램을 통해 이것을 호출하면 프로세스가 중지됩니다.
그런 다음 5 초를 기다렸다가 이제는 정상적으로 작동합니다. 그러나이 시간 초과 값은 시스템 리소스 및 입력 응용 프로그램의 처리량에 따라 달라질 수 있으므로이 문제를 수정하는 더 좋은 방법을 찾아야합니다.
그래서, 내 질문은 우리가 System. Diagnostics를 사용하여 프로세스를 만들고 있다면, OS가 별도의 스레드를 만들고 그것을 기본 스레드 또는 UI 스레드로 만드나요?
또는 System. Threading. Thread와 동일한 CLR 스레드를 만드는 중입니까?
Thread-pool을 사용하여 작업자 스레드를 생성하는 것이 더 좋은 선택일까요?
스레드 풀이 사용자 모드 스케줄링을 사용합니까?
이것에 대한 당신의 도움을 감사하십시오.
System. Diagnostics가 백그라운드 스레드 또는 작업자 스레드도 생성하기 때문에 하루가 끝날 때 변경 사항이 없으므로 별도의 스레드를 다시 만들지 않으므로 그 점을 알아야합니다.
위의 구현과 백그라운드 스레드를 만드는 것의 차이점은 무엇입니까?
응용 프로그램의 내부 및 외부 스레드를 혼란스럽게합니다. UI 스레드에서 WaitForExit을 사용하는 경우. UI 스레드가 응답하지 않게됩니다. 문제가 발생하면 BackgroundWorker의 DoWork 이벤트에 새 프로세스를 생성하십시오. 프로세스가 종료되면 UI 스레드에 경고하는 RunWorkerCompleteEvent가 트리거됩니다.
민 주 (Min Zhu) 마이크로 소프트 우연한 직원의 답변으로 표시 중재자 Monday, July 18, 2011 3:10 AM.
모든 답장.
EnableRaisingEvents = false로 이벤트를 기다리면 WaitForExit을 타이머로 사용하고 있음을 의미합니다. 적절한 값으로 설정하십시오.
EnableRaisingEvents = false로 이벤트를 기다리면 WaitForExit을 타이머로 사용하고 있음을 의미합니다. 적절한 값으로 설정하십시오.
저는 5000을 값으로 주었고 문제를 해결했습니다. 내 걱정은 다른 시스템 자원, 입력 내용 크기 등으로 유사하게 작동합니까?
관련 프로세스가 간격의 끝까지 종료되지 않으면 어떻게됩니까?
Windows는 실시간 운영 체제가 아니므로 모든 타이머는 OS의 일정에 따라 달라집니다. 아마도 System. Timers. Timer가 가장 정확합니다.
& quot; 관련 프로세스가 간격의 끝까지 종료되지 않으면 어떻게됩니까? & quot; 이 기능을 사용 중지했습니다. 이것이 당신이하려는 일이라면, 그것을 가능하게하십시오. 프로세스를 시작하는 데 사용한 스레드를 차단하고 싶지 않으면 백그라운드 스레드에서 시작하십시오. BackgxroundWorker가 이에 적합합니다.
System. Diagnostics가 백그라운드 스레드 또는 작업자 스레드도 생성하기 때문에 하루가 끝날 때 변경 사항이 없으므로 별도의 스레드를 다시 만들지 않으므로 그 점을 알아야합니다.
위의 구현과 백그라운드 스레드를 만드는 것의 차이점은 무엇입니까?
System. Diagnostics가 백그라운드 스레드 또는 작업자 스레드도 생성하기 때문에 하루가 끝날 때 변경 사항이 없으므로 별도의 스레드를 다시 만들지 않으므로 그 점을 알아야합니다.
위의 구현과 백그라운드 스레드를 만드는 것의 차이점은 무엇입니까?
응용 프로그램의 내부 및 외부 스레드를 혼란스럽게합니다. UI 스레드에서 WaitForExit을 사용하는 경우. UI 스레드가 응답하지 않게됩니다. 문제가 발생하면 BackgroundWorker의 DoWork 이벤트에 새 프로세스를 생성하십시오. 프로세스가 종료되면 UI 스레드에 경고하는 RunWorkerCompleteEvent가 트리거됩니다.
민 주 (Min Zhu) 마이크로 소프트 우연한 직원의 답변으로 표시 중재자 Monday, July 18, 2011 3:10 AM.
Microsoft는 Msdn 웹 사이트에 대한 귀하의 의견을 이해하기 위해 온라인 설문 조사를 실시하고 있습니다. 참여를 선택하면 Msdn 웹 사이트를 탈퇴 할 때 온라인 설문 조사가 제공됩니다.

월터의 통나무.
. 학습하면서 글쓰기.
2011 년 11 월 18 일 금요일.
Process. WaitForExit (Int32) 문제가 발생합니다.
보시다시피, 코드는 "cmd. exe"프로세스를 시작하고 실행하려는 명령을 전달합니다.
코드에서 ping - t 8.8.8.8 명령을 사용했습니다. - t 옵션으로 인해 호스트를 멈추지 않고 ping합니다. 무슨 일이야? ping - t 명령과 함께 "cmd. exe"프로세스는 절대로 종료되지 않고 stdout 스트림을 닫지 않으므로 코드가 Output = process. StandardOutput. ReadToEnd (); 왜냐하면 모든 스트림을 읽는 데 성공하지 못하기 때문입니다.
배치 파일의 명령이 어떤 이유로 든 중단되고 위의 코드가 계속해서 몇 년 동안 작동 한 다음 명백한 이유없이 갑자기 멈추는 경우에도 마찬가지입니다.
"cmd. exe"에 첨부하는 명령이나 호출중인 프로세스가 표준 출력이나 표준 오류를 채우면 교착 상태가 발생할 수 있습니다. 이것은 코드가 라인에 도달 할 수 없기 때문입니다.
실제로 우리 프로그램이 스트림의 채워진 버퍼를 읽지 않는다면 자식 프로세스 (ping 명령 또는 배치 파일 또는 실행중인 모든 프로세스)를 실행할 수 없습니다. 코드가 프로세스가있는 줄에 매달려 있습니다. WaitForExit () : 자식 프로젝트가 종료 될 때까지 기다립니다.
두 스트림의 기본 크기는 4096 바이트입니다. 다음 배치 파일을 사용하여이 두 가지 크기를 테스트 할 수 있습니다.

No comments:

Post a Comment