我正在编写一个类库,它将提供一些异步处理,并希望尽量避免在以后遇到线程问题。因此,我会遵循人们可以做出的任何建议,以避免以后遇到问题,而是从良好的设计开始。
我可以看到的一些可能导致问题的情况,并且我不能确定最佳解决方法:
1)我有一个类,它接受一个IEnumerable并使用ToList来构造一个IList。 T是在我的程序集中声明为public的类。在启动异步过程时,此IList用于创建新集合,但此时调用程序集可能正在修改用于生成新内部集合的原始T。
2)我有一个布尔属性,我希望用户在轮询循环中使用它。我很确定这对我在程序集中设置属性不会有问题吗?
3)我经常使用一个内部集合,需要在两个单独的线程上使用。我目前正计划使用同步集合并在需要副本时克隆它...虽然我希望这不会太慢。
4)在我的异步方法中,我想在进度或状态发生变化时触发事件。从处理线程中触发事件时是否需要注意任何事情?再次使用其中的一些我需要传递一个变量,该变量将被视为处理线程内部使用的内容的克隆,以尝试避免用户更改它的任何问题。
提前感谢您的任何帮助!
伊恩
答案 0 :(得分:2)
1)尽可能让你的类型不可变。如果那是不可能的,那么你需要进行适当的锁定。
2)创建基础变量volatile
,以便在所有线程中看到更新
3)我们需要更多信息才能明智地评论。
4)事件处理程序需要知道可以在多个线程上调用它们。如果您需要能够订阅和取消订阅来自各种线程的事件,您还应该查看完全thread-safe event pattern。
答案 1 :(得分:1)
2:提防volatile
(see here,例如为什么);并且不要做“紧”循环。通常首选信号(例如Monitor.Pulse或ManualResetEvent等)
4:如果这是出于显示目的,你需要将这些组织回到UI线程
答案 2 :(得分:0)
谢谢你们,
1)不幸的是,我不认为让我的类型不可变会起作用,所以我可能必须锁定它们。幸运的是,只有在异步方法的初始设置期间,由于各种原因我创建了大多数类实例的简化内部副本,此时我并不关心用户对原始文件做了什么。
2)volatile关键字看起来像我绝对需要的东西,所以将它放入。
3)我将要运行两个线程,这两个线程都需要访问Collection< U&GT ;.一旦他们获得了这个集合,他们将广泛使用它,并且还修改每个U实例的各种属性。一旦他们完成,他们将保存一些简单的属性(例如Guid),抛弃收集并需要重新开始。因此我认为ReadOnlyCollection< U>应该最初创建,然后对于处理开始时的每个线程,它们将运行某种形式的Clone方法,并将输出转换为新的IList< U>例如,他们会做的就是他们正在进行的。
4)这是有用的Jon,事件处理可以从多个线程调用,所以我肯定会使用这些内容。