2010-11-30 7 views
3

사용자가 선택한 시스템에서 쿼리를 실행 한 다음 결과를 단일 보고서로 통합 할 수있는 응용 프로그램 (Delphi 2009 사용)이 있습니다. 응용 프로그램의Windows Server 2003의 다중 스레드 응용 프로그램에서 액세스 위반이 발생했습니다.

간단한 설명 :
사용자는 쿼리 및 쿼리를 통해 실행하는 시스템 그룹을 선택합니다. 쿼리는 쿼리를 실행하는 새 스레드를 만들고 TADOQuery를 사용하여 실제로 스레드 내에서 쿼리를 실행하여 모든 시스템에서 동시에 실행됩니다. 쿼리가 실행되면 TADOQuery.SaveToFile이 호출되어 pfXML을 매개 변수로 전달하여 결과를 XML 문서에 저장합니다. 모든 쿼리가 실행되면 응용 프로그램은 모든 XML 문서를 구문 분석하고 단일 XML 문서로 통합합니다. 그런 다음 사용자는 보고서를로드하여 TADOQuery.LoadFromFile을 호출하여 보고서를로드하고이를 TListView에 표시 할 수 있습니다.

사용자가 너무 많은 쿼리를 제출하여 (너무 많은 스레드를 시작하여) PC에 과부하를주지 않도록하기 위해 레코드 배열을 사용하여 큐를 구현했습니다. 각 레코드는 쿼리 이름, 시스템, 상태 (실행 중, 완료 또는 보류 중)와 같은 정보를 보유합니다. 큐를 구현하는 또 다른 이유는 사용자가 동시에 여러 쿼리를 제출할 수 있다는 것입니다 (즉, 해당 큐를 기다릴 필요가 없습니다). 첫 번째는 다른 것을 제출하기 전에 완료해야 함). 레코드 배열은 아마도 큐를 구현하는 가장 효율적인 방법은 아니지만 작동합니다. 동시 실행 스레드 수를 100으로 유지합니다 (사용자가 변경할 수 있음). 큐에서 관리하는 프로 시저와 스레드 내에서 실행 된 쿼리 완료를 동기화하여 스레드를 실행할 때 새 스레드를 시작합니다. 어떤 시점에서도 메모리 사용량은 약 25-30K 올라갑니다.

최종 정보는 응용 프로그램에 작업 스케줄러가 포함되어있어 사용자가 쿼리 실행시기를 지정할 수 있도록하는 것입니다. 이 기능은 고객이 서버에서 소프트웨어를 무인으로두고 매일 매일 특정 시간에 보고서를 작성하려는 고객이 사용합니다.

문제 :
응용 프로그램이 Windows XP에서 정상적으로 실행됩니다. 얼마나 많은 쿼리가 제출 되더라도 상관 없습니다. 그러나 Windows Server 2003에서 실행되는 임의의 시간이 지나면 응용 프로그램이 실행되지 않습니다. 응용 프로그램과 상호 작용을 시도하거나 닫으면 액세스 위반이보고됩니다. 나는 그것이 내게 어디에서 왔는지, 무엇이 그것을 일으키는 지 알기 힘든 삶을 살 수 없다.

내 첫 번째 생각은 운영 체제의 메모리 관리 구현과 관련이 있을지 모르지만 문제의 원인을 파악할 수 없습니다. 전체 디버그 모드에서 FastMM4를 사용하는 응용 프로그램 버전을 컴파일했으나 해제되어서는 안되는 메모리를 해제하거나 해당 줄에있는 내용을보고하지 않으며 정상적인 환경에서 실행할 때 메모리 누수가 발생하지 않습니다. , 그래서 비록 내가 여전히 메모리 관리에 문제가 있다고 확신하지만, 나는 그것이 무엇인지 알 수 없다.

액세스 위반이 발생하면 내 응용 프로그램의 임시 폴더에 많은 보고서 파일이 있음을 알 수 있습니다. 즉, 일부 쿼리가 실행되어 결과가 반환되지만 모든 스레드가 완료되지 않고 보고서는 아직 통합되지 않았다). 또한 작업 스케줄러는 최대 스레드 (기본적으로 100 개)가 실행 중이기 때문에 실행되지 않은 큐에 작업을 제출하고 작업을 제출했다고보고합니다 (매 20 분마다 스케줄러를 통해 작업을 제출하여 테스트했습니다) 밤새 신청서를 남겨 둡니다).

이렇게하면 대기열 (레코드 배열) 처리에 문제가있을 수 있습니다.스레드가 완료되고 큐를 관리하는 프로 시저와 동기화되지만 큐에 문제가있는 경우 다음 스레드는 시작되지 않으며 모든 쿼리가 완료되지 않았으므로 임시 폴더의 보고서가 나타납니다 통합되지 않습니다. 이것은 응용 프로그램이 붙어있는 시점 인 것 같습니다.

따라서 두 가지 문제가 있습니다.
1. 액세스 위반의 원인은 무엇입니까? 대기열과 관련이 있습니까? 아니면 다른 것입니까?
2. 응용 프로그램이 Windows XP에서는 잘 작동하지만 Windows Server 2003에서는 넘어지지 않는 이유는 무엇입니까?

UPDATE
나는 그것이 윈도우 서버 2003이 제한처럼 보이게하지 않도록, 지금은 Windows XP에서 오류가 발생 할 수있는 테스트 중에 정도로 응용 프로그램을 타자 관리했습니다 XP보다 Windows Server 2003에 훨씬 더 빠른 것처럼 보입니다.

시스템 그룹에 대해 쿼리 그룹을 실행하면 모든 보고서가 작성 될 때까지 기다린 다음 프로세스를 반복하면 결과적으로 쿼리가 제출되지 않고 응용 프로그램의 아무 곳이나 두 번 클릭하면됩니다 down)을하면 액세스 위반이 발생합니다 (메모리 주소는 다양하지만 항상 주소 0을 쓰는 것은 아니지만 항상 쓰기).

나는 MadExcept를 사용하여 콜 스택을 추적했지만 예외적으로 아무 것도 표시하지 않습니다. 두 번 클릭 이벤트가 발생하는 코드 행만 표시됩니다.

뭔가가 제출되고 또한 액세스 위반을 일으키는 (내가 추측 할 수있는) 중지하고 있지만 무엇이 될지 알 수 없습니다.

+0

액세스 위반에 오류가 있습니까? 그 주소를 소스 코드에서 볼 수 있습니까? 읽기 또는 쓰기 위반입니까? 읽은 경우 0, 현명한 수 또는 마법 상수를 읽었습니까? 예외가 발생했을 때 MadExcept/JCL/등을 사용하여 콜 스택 추적을 시도 했습니까? –

+0

오류 주소가 있지만 매번 오류 주소가 없습니다. 읽기 위반으로, 0을 읽었습니다. 전 (아직 델파이가 아닌) 그렇게 해본 적이 없기 때문에 콜 스택을 추적하려고하지는 않았지만 시도해 보겠습니다. – Jeedee

+0

저는 MadExcept를 사용하여 호출 스택을 추적했지만 예외적 인 사항은 없습니다. 자세한 정보는 위의 업데이트를 참조하십시오. – Jeedee

답변

0

나는 마침내이 문제를 추적 할 수 있었고, 당신은 그것을 모범생 오류라고 부를 수 있다고 생각합니다!

각 스레드 내에서 쿼리를 실행하는 데 사용되는 TADOQuery 구성 요소를 만듭니다. ,

adoqry := TADOQuery.create(frmMain); 
try 
    <code> 
finally 
    freeAndNil(adoqry); 
end; 

문제가 응용 프로그램의 메인 화면이 될하기 위해 TADOQuery 구성 요소의 소유자를 설정하는 것 같습니다 : 나는 주요 형태로 소유자를 설정할 수 있지만 스레드가 종료 그 전에, 나는 메모리를 삭제 즉, 응용 프로그램이 닫힐 때 주 화면이 메모리를 확보하려고 시도하지만 사용자가 수천 개의 쿼리를 실행하는 동안 응용 프로그램이 계속 켜져있는 경우 이러한 참조가 쌓여서 결국 응용 프로그램이 포기하여 액세스 위반을 던지기 시작합니다 .

TADOQuery 구성 요소의 소유자를 nil로 변경했으며 수천 건의 쿼리를 실행 한 후에도 응용 프로그램이 정상적으로 작동합니다.

0

실제 답변보다 문제 해결 팁이 더 많습니다 ... # 2의 경우 하드웨어가 동일합니까? 그렇지 않다면 이것은 정말로 단일 코어 대 멀티 코어 (또는 프로세서)의 문제 일 수 있습니다. 멀티 스레드 응용 프로그램이기 때문에 여러 프로세서/코어에서 다르게 동작 할 것이라고 기대하는 것은 무리가 아닙니다. 따라서 너무 많은 변수 (하드웨어 대 OS)로 문제를 망칠 필요가 없는지 확인하십시오.

+1

예, 동일한 하드웨어. 또한 Win2k3을 실행하는 다른 하드웨어에서 실행중인 응용 프로그램을 동일한 결과로 실행 시켰으므로 하드웨어 문제가 아닌 OS 관련 것으로 보입니다. – Jeedee

+0

대기열에서 교착 상태로 보입니다. 하나의 CPU/코어에 선호도를 설정하고 문제가 동일하게 유지되는지 확인할 수 있습니다. – Glenner003

관련 문제