将IDisposable作为参数传递

时间:2011-09-02 22:45:17

标签: .net methods parameter-passing idisposable disposing

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

E.g。

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 个答案:

答案 0 :(得分:5)

我认为你最好带一个创作代表来保证对象的处理。

示例

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
    }
}

答案 1 :(得分:2)

不,主人应该处理它。所有者通常是首先创建IDisposable实例的对象。您可以阅读IDisposable最佳做法here

  

传递性地处理您的类型中定义的任何一次性字段   来自你的Dispose方法。你应该在任何字段上调用Dispose()   其生命周期是您的对象控制的。例如,考虑一个案例   您的对象拥有私有TextReader字段的位置。在你的类型   Dispose,你应该调用TextReader对象的Dispose   反过来处理其一次性领域(Stream和Encoding,for   例子),等等。如果在Dispose内部实现(bool处理)   方法,这应该只在disposing参数是   在此期间不允许使用真实触摸的其他托管对象   定稿。 此外,如果您的对象不拥有给定的对象   一次性物品,不应该像其他物品那样试图处理它   代码仍然可以依赖它活跃。这两者都可能导致   微妙的检测错误。

最好尽量减少传递IDisposable实例,这样您就不必过多考虑所有者。

答案 2 :(得分:0)

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

一般来说,“所有者”应该处置该对象,但是你的工作就是找出那个对象。它可能不是创建者,也可能不是你的情况下的调用者。

答案 3 :(得分:0)

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

  1. SoundSource,它实现一个GetAudio方法,返回声音的下一个'n'个样本。 SoundSource实现IDisposable,因为它可用于从文件流式传输音频;如果配置不当,文件将不会关闭。
  2. AsyncSoundPlayer,它实现一个接受SoundSource并开始播放的PlaySound方法,中止任何以前播放的声音。

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