繁体   English   中英

通过C#中的反射访问数据时的并发问题

[英]Concurrency issues while accessing data via reflection in C#

我目前正在编写一个可用于显示某些正在运行的代码(主要是公共和私有字段和属性)的内部状态的库。 在不同的线程中访问对象,以将其信息放入窗口中供用户查看。 问题是,有时我走很长的IList时,其结构可能会更改。 程序中被“监视”的某些代码可能会添加一个新项目,甚至更糟的是删除其中的一些代码。 这当然会导致整个崩溃。

我提出了一些想法,但恐怕它们不太正确:

  1. 在我走时锁定要访问的列表。 我不确定这是否行得通,因为正在使用的IList可能尚未被锁定以用于另一侧的写入。

  2. 让所关注的代码知道我的存在,并提供一些接口以允许同步。 (我真的很希望它是完全透明的)。

  3. 作为最后的选择,将每个读取访问权限放入try / catch块中,并假装好像没有任何异常。 (无法想到一个实际可行的更丑陋的解决方案)。

提前致谢。

使事情对被监视的代码“透明”的唯一方法是使监视代码在状态改变时变得健壮。

一些建议

  1. 不要遍历共享列表-尽快将列表的副本复制到本地List实例中。 一旦有了本地(非共享)实例列表,任何人都无法使用该列表。

  2. 使事情变得尽可能健壮-将每次读取都放入try / catch可能会令人讨厌,但是您可能需要这样做。

尽管我喜欢贝文(Bevan)复制列表以供本地读取访问的想法,但是如果列表特别大,那可能不是一个真正可行的选择。

如果确实需要对这些列表的无缝,透明,并发访问,则应查看.NET库的Parallel Extensions。 它目前可用于.NET 2.0至3.5作为CTP。 这些扩展将与一些其他集合一起正式包含在.NET 4.0中。 我认为您会对CTP的BlockingCollection感兴趣,它将为您提供所需的透明并发访问。 显然,与涉及同步的任何线程化内容一样,性能也会受到影响,但是这些集合的优化程度很高。

选项3可能很难看,但这看起来类似于Visual Studio监视窗口使用的方法,我会选择这种方法。

在Visual Studio中,通常可以将监视设置在某些列表或集合上,稍后,当监视由于用户或代码状态更改而无法评估某个值时,该监视仅显示异常。

当处理这种无限可能时,这是最可靠的方法。 事实是,如果您的观看代码旨在支持尽可能多的场景,则您将无法事先考虑所有情况。 下一个最好的方法是很好地处理和呈现异常。

顺便说一句,有人提到锁定数据结构将起作用。 如果“其他代码”也未使用锁进行同步,则情况并非如此。 实际上,这两段代码都必须锁定相同的同步对象,如果您不控制其他代码,则不太可能。 (我认为您在问题中提到了这一点,所以我同意。)

据我了解,您不想对正在监视的代码有任何依赖性/要求,也不希望对代码的编写方式施加任何约束。

尽管这是我最喜欢的“观察者”代码编写方法,但是这会使您的应用程序面对范围很广的代码和行为,从而可能导致崩溃。

因此,正如我之前所说,我的建议是第一步使观察者“稳健”。 您应该为代码中任何地方出现的错误做好准备,因为考虑到“透明度”,很多事情都有可能出错! (请注意将try / catch放在哪里,多次进入和离开try块可能会对性能产生明显影响)

完成代码的健壮性之后,接下来的步骤将是使代码更可用,并避免可能导致异常的情况,例如您提到的“列表”。 例如,您可以检查被监视的对象,看看它是否是一个列表,并且它不是太长,请首先对其进行快速复制,然后再进行其余操作。 这样,您就消除了可能导致代码抛出的大量可能性。

锁定列表将起作用,因为它被修改,正如您通过崩溃所观察到的那样:)

不过在我看来,我会避免锁定(因为似乎您的线程只是“观察者”,不应真正中断)。

在此基础上,我将尝试处理确定丢失的东西的情况。 这不可能吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM