c# – 如何避免RCW清理比赛

c# – 如何避免RCW清理比赛,第1张

概述我有一个gui应用程序,定期显示cpu负载.负载由StateReader类读取: public class StateReader{ ManagementObjectSearcher searcher; public StateReader() { ManagementScope scope = new ManagementScope("\\\\loca 我有一个gui应用程序,定期显示cpu负载.负载由StateReader类读取:

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();    }}

使用反应式扩展更新gui:

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();

现在当我退出我的应用程序时,我收到一个错误说

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.

如果我没有读取cpu负载,但只提供一些随机值,则不会出现此错误,因此错误以某种方式连接到读取负载.此外,如果我在Application.Run(gui)之后放置一个断点并在那里稍等一下,那么错误似乎并不常见.

从这个和我的谷歌搜索我认为使用管理命名空间中的类创建一个后台线程,引用包含在运行时可调用包装器中的COM对象,当我退出我的应用程序时,该线程没有时间正确关闭RCW,导致我的错误.这是正确的,我该如何解决这个问题?

我编辑了我的代码以反映我的反应,但我仍然得到同样的错误.代码更新了三点:

> StateReader是disposable,将其ManagementObjectSearcher置于dispose方法中
我在main方法中的Application.Run之后调用StateReader对象上的dispose
>在cpuLoad中,我处理了ManagementCollection和每个ManagementObject
>在我的main方法中,我在FormClosing上的事件处理程序中处理订阅对象
在gui上.这应该确保gui关闭后不会生成任何事件.

现在,在StateReader中代码的相关部分:

// give the maximum load over all corespublic 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();

还有什么我可以做的,以避免我得到的错误?

解决方法 我认为你需要使StateReader一次性使用并在退出应用程序之前将其处理掉. StateReader应该处理搜索者.但是,我认为真正的问题是您没有在cpuLoad中部署ManagementObject.如果GC在cpuLoad之后运行,RCW将被释放.但是,如果您在GC之前退出,则可能会触发您看到的异常.

I think that using the classes in the management namespace creates a background thread that references a COM object wrapped in a Runtime Callable Wrapper

Observable.Interval创建一个后台线程,cpuLoad在该线程上执行.

总结

以上是内存溢出为你收集整理的c# – 如何避免RCW清理比赛全部内容,希望文章能够帮你解决c# – 如何避免RCW清理比赛所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1228759.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存