주기적으로 CPU 부하를 표시하는 GUI 응용 프로그램이 있습니다. 부하는 StateReader 클래스에 의해 읽기 :RCW 정리에서 레이스를 피하는 방법
GUI는 반응 확장 갱신된다public class StateReader
{
ManagementObjectSearcher searcher;
public StateReader()
{
ManagementScope scope = new ManagementScope("\\\\localhost\\root\\cimv2");
ObjectQuery query = new ObjectQuery("select Name,PercentProcessorTime from Win32_PerfFormattedData_PerfOS_Processor where not Name='_Total'");
searcher = new ManagementObjectSearcher(scope, query);
}
// give the maximum load over all cores
public UInt64 CPULoad()
{
List<UInt64> list = new List<UInt64>();
ManagementObjectCollection results = searcher.Get();
foreach (ManagementObject result in results)
{
list.Add((UInt64)result.Properties["PercentProcessorTime"].Value);
}
return list.Max();
}
}
: 내 응용 프로그램을 종료 할 때, 나는
RaceOnRCWCleanup was detected.
An attempt has been mad to free an RCW that is in use. The RCW is use on the
active thread or another thread. Attempting to free an in-use RCW can cause
corruption or data loss.
말하는 오류가 이제
var gui = new GUI();
var reader = new StateReader();
var sub = Observable.Interval(TimeSpan.FromSeconds(0.5))
.Select(_ => reader.CPULoad())
.ObserveOn(gui)
.Subscribe(gui.ShowCPUState);
Application.Run(gui);
sub.Dispose();
을 이 오류는 CPU 부하를 읽지 않고 일부 임의의 값만 제공하면 나타나지 않으므로 오류가 어떻게 든로드 읽기에 연결됩니다. 또한 Application.Run(gui)
뒤에 중단 점을 넣고 약간 기다리면 오류가 자주 발생하지 않는 것 같습니다.
이것과 내 인터넷 검색에서 나는 관리 네임 스페이스의 클래스를 사용하여 런타임 호출 가능 래퍼에 래핑 된 COM 객체를 참조하는 백그라운드 스레드를 만들고 응용 프로그램을 종료하면 해당 스레드에 시간이 없다고 생각합니다. RCW를 제대로 닫아서 실수로 이어집니다. 이게 맞습니까? 어떻게이 문제를 해결할 수 있습니까?
내가 가진 응답을 반영하도록 코드를 편집했지만 여전히 동일한 오류가 발생합니다. 이 코드는 세 가지 점에 업데이트됩니다
- StateReader은 일회용이며, Dispose 메서드 에서의 ManagementObjectSearcher을 처분하고 난 처분 CPULoad에서
- 내 주요 방법에 Application.Run 후 StateReader 개체에서 Dispose를 호출해야 ManagementCollection 및 그 안에있는 각 ManagementObject
- 내 주요 메소드에서 gui의 FormClosing
의 이벤트 처리기에 구독 객체를 삭제합니다. 이렇게하면 gui가 닫힌 후에 이벤트가 생성되지 않습니다.
코드의 관련 부분은 StateReader에, 지금 :
// give the maximum load over all cores
public UInt64 CPULoad()
{
List<UInt64> list = new List<UInt64>();
using (ManagementObjectCollection results = searcher.Get())
{
foreach (ManagementObject result in results)
{
list.Add((UInt64)result.Properties["PercentProcessorTime"].Value);
result.Dispose();
}
}
return list.Max();
}
public void Dispose()
{
searcher.Dispose();
}
그리고 내 주요 지역 : 내가 얻을 오류를 방지하기 위해 할 수있는 뭔가가
gui.FormClosing += (a1, a2) => sub.Dispose();
Application.Run(gui);
reader.Dispose();
있는가 ?
진단이 정확합니다. 그것은 유일한 문제는 아니지만. ObserveOn (GUI) 호출 역시 매우 번거로운 일입니다. 양식을 닫을 수있게하기 전에 더 이상 알림을 생성 할 수 없도록해야합니다. 이것은 스레드가 만연하게하는 위험 요소입니다. –
@ 한자 Passant : FormClosing에서 구독을 처분하기 위해 코드를 편집했습니다. 이것이 당신이 언급 한 문제를 해결한다고 말하겠습니까? 저는 버튼 클릭 등과 같이 사용자와 상호 작용하는 사건을 제외하고는 양식에 다른 이벤트가 없습니다. – Boris
아마도 Dispose()를 호출했지만 아직 실행을 시작하지 않은 TP 스레드가 예약 된 경우 스레딩 레이스 일 것입니다. 나는 반응 배관을 충분히 잘 모른다. –