I have 2 rules about Disposeables that have never failed me:
- Never split up the creation and disposing. Create, Use, Dispose. All in teh same piece of code, ideally using a using block.
- There are cases when you can not follow Rule 1. Mostly because your class contains something Disposeable, that needs to be kept open. In that case you implement IDisposeable for the sole purpose of relaying the dispose call. Indeed that is about the reason 95% of all classes do implement IDisposeable - because they may have to do that kind of relay.
In case 2 whoever uses your class follows rule 1.
Making a class field of something Disposeable except a case 2, will really only risk stuff like "trying to work with it when already disposed" and "trying to do stuff with it, when nobody should be doing stuff with it". It will just cause issues.
Edit:
Based on your comments, you are mostly worried about the polling application side. If you do polling, there is a very common pattern to have teh whole polling work - loop and all - run in an alternative task or thread. This is my rate-limit code for multithreading, modified with a using:
integer interval = 20;
DateTime dueTime = DateTime.Now.AddMillisconds(interval);
using(someThingDisposeable){
while(true){
if(DateTime.Now >= dueTime){
//insert your work with someThingDisposeable here
//Update next dueTime
dueTime = DateTime.Now.AddMillisconds(interval);
}
else{
//Just yield to not tax out the CPU
Thread.Sleep(1);
}
}
}
Modifying it for other forms of Multitasking, only requires using their equivalent for Thread.Sleep
.
This code will keep the connection open as long as everything goes well. It will not query the datasource more often then you tell it too. It will never stack up operations. But it will still reliably close the connection on Exceptions. Do not forget to expose the Exception - with Multitasking it is notoriously easy to forget that part. It is a full case 1, minus needing to re-create the connection over and over.