同时允许两个线程编辑同一对象的不同属性是否安全?

10
我正在编写一个目录应用程序,通过解析文件并提取信息,将每个文件的信息存储在对象实例中。除了从文件中提取的数据外,这些对象还具有其他元数据属性(作者、标签、注释等),后者会在单独的XML文件中存储。
从文件中提取数据是一项耗时的过程,因此我将其运行在单独的线程上。从文件中提取的属性只能来自文件,因此具有[ReadOnly]属性以防止用户编辑它们。另一方面,元数据属性仅由用户填充,因此不是只读的。我允许用户通过PropertyGrid查看/编辑这些对象。
因此,如果提取进程在一个线程上运行,并且正在填充对象的文件属性,让用户同时编辑元数据属性是否存在危险?我正在尝试决定是否使用模态界面,以防止用户在提取完成/取消之前做任何事情,或使用非模态界面,允许他们在提取运行时继续工作。
4个回答

5
具体针对你的问题:没有问题。
需要注意的是,当后台线程写入属性时,不能在UI线程中读取这些属性。如果无法保证此条件,则必须使用锁定、将写操作传递到UI线程(使用control.Invoke()BackgroundWorker),或确保写入是指向不受后台线程编辑但可从UI线程中看到的对象指针的原子写入。我不会认为像List<T>这样的标准容器是线程安全的。

所以,如果提取线程更新了用户当前在属性网格中查看的对象的属性,直到用户重新选择属性网格中的对象,属性网格才会更新吗?我对此没有问题。我更担心的是程序崩溃或数据损坏。所有属性都是原始类型,如布尔型、整型、双精度型和字符串型。 - Eric Anastas
我提出这个问题是因为可能会发生崩溃,但它主要适用于更复杂的类型。实际上,double不能保证被写入原子性,因此如果读取和写入同时发生,它可能显示错误。请参见以下链接中的注意事项:http://msdn.microsoft.com/en-us/library/system.double.aspx - user180326
确实很不可能,而且根据你告诉我的情况,在你的应用程序中也没有关系。但我认为仅仅说没有问题是不正确的,我只是想让你了解不太可能发生的最坏情况,并让你自己做出判断。 - user180326
1
@Eric - 你花了很多精力来合理化不使用锁的做法。我强烈建议按照“正确”的方式来做,并在性能出现问题时进行优化。 “非常,非常,非常不可能”并没有让我感到温暖和舒适。 - Mark Brackett
@Mark - 同意。令人惊奇的是,只要有付费客户开始使用你的代码,一些非常、非常、非常不可能发生的事情就会迅速发生。 - Rory MacLeod
显示剩余2条评论

1
假设“正常”的属性 - 例如,自动实现或简单的字段支持:
public class MyClass {
    [ReadOnly]
    public string FileAuthor { get; set; }

    public string MetaDataAuthor { 
       get { return _metaDataAuthor; }
       set {  _metaDataAuthor = value; }
    }
    private string  _metaDataAuthor;
}

更改不同线程上的值不应该有任何问题。同步写入不同变量是不必要的。

然而,如果PropertyGrid显示文件属性(如FileAuthor)- 您可能希望同步读取(绑定PropertyGrid)和写入(文件提取)这些属性。


所有的属性都是基本类型的“普通”属性。 - Eric Anastas

1
一般来说,如果属性没有引用共享状态,那么即使它们是同一个对象的一部分,它们也可以在不同的线程上进行更新而不会出现问题。

1
你可以自由地这样做,只要你确定一个属性的更改不会导致另一个在另一个线程中可能被修改的属性发生更改。简言之,如果这些属性没有共享的数据,那么这将非常有效!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接