8

将 IDisposable 作为参数传递给方法并将其放置在该方法中是否是一种好习惯。当您必须使用多个线程时,这是不可避免的。好吧,最佳实践说所有者(调用者)应该处理它。

例如

public void MyMethod(MyClass reader){
    using(reader){
        //some code
    }
}

如果所有者(创建线程)不再存在怎么办?例如

interface IReader : IDisposable {
    string Read();
}

public class MyReader : IReader {

    public string Read()
    {
        return "hellow world";
    }
    public void Dispose()
    {
        //dispose code
    }
}

在这里你会发现问题...

public void Start() {
    MyReader[] readerSet = new MyReader[5];
    for (int i = 0; i < readerSet.Length; i++) {
        readerSet[i] = new MyReader();
    }
    foreach (IReader reader in readerSet) {
        ThreadPool.QueueUserWorkItem(new WaitCallback(Run), reader);
    }
    //exit after creating threads
}


public void Run(Object objReader) {
    IReader reader = (IReader)objReader;
    using (reader) { 
    //use the reader
    }
}
4

4 回答 4

6

我认为您最好采用创建委托来保证对象的处置。

例子

public void Start() {
    var makeReader = new Func<IReader>(() => new MyReader()); 
    for (int i = 0; i < 5; i++) {
        ThreadPool.QueueUserWorkItem(Run, makeReader);
    }
}    

public void Run(Object state) {
    var makeReader = (Func<IReader>)state;
    using (var reader = makeReader()) { 
        //use the reader
    }
}
于 2011-09-02T22:52:52.223 回答
3

不,主人应该处置它。所有者通常是首先创建 IDisposable 实例的对象。您可以在此处阅读有关 IDisposable 最佳实践的信息。

请通过 Dispose 方法传递地处理您的类型中定义的任何一次性字段。您应该在对象控制其生命周期的任何字段上调用 ​​Dispose()。例如,考虑您的对象拥有私有 TextReader 字段的情况。在您的类型的 Dispose 中,您应该调用 TextReader 对象的 Dispose,这将依次释放其一次性字段(例如 Stream 和 Encoding),等等。如果在 Dispose(bool disposing) 方法中实现,则只有在 disposing 参数为 true 时才会发生这种情况——在最终确定期间不允许接触其他托管对象。此外,如果您的对象不拥有给定的一次性对象,则不应尝试处置它,因为其他代码仍可能依赖它处于活动状态。这两种情况都可能导致难以察觉的错误。

尽量减少传递的 IDisposable 实例可能是一个好主意,这样您就不必过多地考虑所有者。

于 2011-09-02T22:46:56.963 回答
0

这完全取决于你的具体情况。

通常,“所有者”应该处理该对象,但您的工作是弄清楚这是谁。在您的情况下,它可能不是创建者,也可能不是调用者。

于 2011-09-02T22:51:11.030 回答
0

从创建到 Dispose 调用的任何时刻,IDisposable 的任何实例都应该有一个负责删除它的所有者。通常,IDisposable 的所有者将是创建它的实体,但在某些情况下,让对象将 IDisposable 的所有权移交给另一个对象可能会有所帮助。例如,考虑以下两个假设类:

  1. SoundSource,它实现了一个 GetAudio 方法,该方法返回一个声音的下一个“n”个样本。SoundSource 实现 IDisposable 是因为它可用于从文件流式传输音频;如果没有正确处理,文件将不会被关闭。
  2. AsyncSoundPlayer,它实现了一个 PlaySound 方法,该方法接受一个 SoundSource 并开始播放,中止任何以前播放的声音。

在许多情况下,加载 SoundSource 的例程不会真正关心它何时播放完毕。让播放例程获得 SoundSource 的所有权会更方便。请注意,在某些情况下,请求播放的例程可能希望保留 SoundSource 的所有权。最好的方法是允许例程的调用者指定其是否希望保留或移交传入 IDisposable 的所有权的方法。

于 2011-09-03T02:35:16.557 回答