假设我有一个实现IDisposable接口的类.像这样的东西:
MyClass使用一些非托管资源,因此IDisposable的Dispose()方法会释放这些资源.MyClass应该像这样使用:
using ( MyClass myClass = new MyClass() ) { myClass.DoSomething(); }
现在,我想实现一个异步调用DoSomething()的方法.我向MyClass添加了一个新方法:
现在,从客户端来看,MyClass应该像这样使用:
using ( MyClass myClass = new MyClass() ) { myClass.AsyncDoSomething(); }
但是,如果我不做任何其他事情,这可能会失败,因为在调用DoSomething()之前可能会释放对象myClass(并抛出意外的ObjectDisposedException).因此,应该延迟对Dispose()方法(隐式或显式)的调用,直到完成对DoSomething()的异步调用.
我认为Dispose()方法中的代码应该以异步方式执行,并且只有在解析了所有异步调用之后才能执行.我想知道哪个可能是实现这一目标的最佳方法.
谢谢.
注意:为简单起见,我没有详细介绍如何实现Dispose()方法.在现实生活中,我通常遵循Dispose模式.
更新:非常感谢您的回复.我感谢您的努力.正如chakrit 评论的那样,我需要多次调用异步DoSomething.理想情况下,这样的事情应该工作正常:
using ( MyClass myClass = new MyClass() ) { myClass.AsyncDoSomething(); myClass.AsyncDoSomething(); }
我将研究计数信号量,它似乎是我正在寻找的.这也可能是一个设计问题.如果我发现它很方便,我将与您分享一些真实案例和MyClass真正做的事情.
看起来你正在使用基于事件的异步模式(有关.NET异步模式的详细信息,请参见此处),因此您通常拥有的是在异步操作命名时触发的类上的事件DoSomethingCompleted
(请注意AsyncDoSomething
应该真的被称为DoSomethingAsync
正确遵循模式).有了这个事件暴露你可以写:
var myClass = new MyClass(); myClass.DoSomethingCompleted += (sender, e) => myClass.Dispose(); myClass.DoSomethingAsync();
另一种方法是使用IAsyncResult
模式,您可以将调用dispose方法的委托传递给AsyncCallback
参数(有关此模式的更多信息也在上面的页面中).在这种情况下,你有BeginDoSomething
和EndDoSomething
方法而不是DoSomethingAsync
,并称之为...
var myClass = new MyClass(); myClass.BeginDoSomething( asyncResult => { using (myClass) { myClass.EndDoSomething(asyncResult); } }, null);
但无论你采用哪种方式,都需要一种方法让调用者知道异步操作已经完成,这样它就可以在正确的时间处理对象.
异步方法通常有一个回调,允许你在完成后做一些操作.如果这是你的情况,它将是这样的:
// The async method taks an on-completed callback delegate myClass.AsyncDoSomething(delegate { myClass.Dispose(); });
另一种方法是异步包装器:
ThreadPool.QueueUserWorkItem(delegate { using(myClass) { // The class doesn't know about async operations, a helper method does that myClass.DoSomething(); } });