Hi I've been thinking for some time that Subject<T> disposes all the subscriptions based on it if you manually call its Dispose method. But I've recently found it doesn't work that way, it just clears its inner collection of observers and substitutes it with a DisposedObserver helper class instance.
I found myself a little confused about the behaviour, just assumed that the "normal" would be just propagate and dispose all the suscribers. Later, trying to figure out why is designed this way, I guessed a couple of reasons why they designed this way.
The suscriber may be a composition that depents partially on the subject , so full propagation of disposal doesn't make sense. ie. Merge is not disposed just because one of the sources was disposed, as everyone expects.
Subject.Dispose It is semantically equivalent to a continuation with Observable.Never from the side of the observer. The Subject.Dispose caller can also call OnComplete or OnError if wanted to signal error or completion before disposal (because they are on the same scope).
Edit Note:
Sorry for the unclear question. I already understand how to use it, this was more a design question. Let me state it more clearly.
Why do you think the designers of Rx made Dispose behaviour that way?
(the two points above are my answer trial)
A subject should indicate it is done by sending OnComplete or possibly OnError. This is idiomatically and grammatically correct Rx. Subscribers are responsible for ending their subscriptions by disposing them. You should write Observables such that they clean up resources once they are "done" even if subscribers have not unsubscribed.
Related
Is there any way to add an event to the current thread that is executed when the thread ends.
I have a solution where we create resources that we want to re-use but still need to have disposed when the thread ends to prevent leaks and I cannot trust every one to be diligent in adding manual dispose calls to their code.
I could do this with a wrapper around the thread but that will not be a reliable solution as I will not be able to make 100 % sure every one would use the wrapper and sometimes this might need to be added into an existing thread.
So I would need my resource to be able to add a dispose event to be called when the tread finishes.
Is this possible in C#
are we all talking about the same .net here? just impliment Finalize
http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.100).aspx
http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx
this is the way to tell the 'GC' to do some additional actions when clearing a resource.
If you expect developers may forget to call Dispose() on object, there is another pattern which can be used to force them to call such methods. This is inspired from how database transactions work.
The idea is you use the object which exposes two methods. Complete() and RollBack(). At the end of object lifespan, developer needs to call Complete() for things to work. If he fails to comply, object's destructor (or Dispose()) will call RollBack(). In .NET TransactionScope class is a good example.
In your case you need to encapsulate your thread object inside this class. The caller doesn't directly deal with thread object, but it deals with this class object.
Is there any way to add an event to the current thread that is executed when the thread ends?
No, there's no event in the framework that you can subscribe to.
As you say, one solution would be to wrap the thread main method with a try / finally block.
Another solution would be to rely on the GC. If someone forgets to call Dispose, the destructor will still be called some time after the object goes out of scope - it will be called on the finalizer thread, though.
How much work should be done in a Dispose method? In constructors I've always taken the stance that you should only do what is absolutely necessary to instantiate the object. This being the case I've also always taken the approach that you should ONLY be cleaning up open resources when disposing. Closing files, freeing memory, disposing of child disposable object, etc. You shouldn't be doing lengthy processes like touching files, accessing databases and such in the Dispose method.
Am I wrong? Are those action's OK as long as you are handling any possible exceptions so they don't bubble out of the method? I just don't think doing a lot in Dispose is a good idea. I would like to know what the community thinks.
Am I wrong?
No, you are right. In general the Dispose method is used to clean the unmanaged resources that your class might have allocated.
But that's difficult to generalize. There are cases where the Dispose method is simply used to ensure that some operation executes. For example in ASP.NET MVC there's the Html.BeginForm helper which is used like that:
using (Html.BeginForm())
{
}
and all that the Dispose method does is render a closing </form> tag. So as you can see people could be creative with the pattern and it is very difficult to draw conclusions without a specific scenario.
But in the most common situations it's used to release unmanaged resources.
"It depends". What kind of database/file access are we talking about? Say for example that your disposable object is some sort of logger and you use it in the following pattern
using(Logger logger = new Logger())
{
foo.PerformTask();
}
I think it would be perfectly acceptable for logger to write out "Log started" in the constructor "Log Completed" in Dispose.
How much work should be done in a Dispose method?
This depends, are you implementing the IDispose interface just for the convenience of a 'using' statement, or are you implementing the full IDisposable pattern? In the later case of a full disposable pattern it is still acceptable to perform more complex actions provided that you're 'disposing' parameter is true (i.e. you are not in GC).
When you are defining a finalizer that calls the Dispose method there really is not too much to be concerned about. Similar uses/abuses of the IDisposable interface mentioned already be others (i.e. using (Html.BeginForm())) are capable of performing any action. Often this can greatly reduce code complexity and prevent coders from accidentally forgetting to perform some closing action. One down (or up) side to this is that code executes a little differently inside a finally block.
In constructors I've always taken the stance that you should only do what is absolutely necessary to instantiate the object.
Objects, IMHO, should be valid post construction. So if you have a lot of work to do to construct something so be it. Don't think of the workload involved, think of the consumer of you're object and it's usability. Post-construction Initialize() methods suck ;)
This being the case I've also always taken the approach that you should ONLY be cleaning up open resources when disposing. Closing files, freeing memory, disposing of child disposable object, etc. You shouldn't be doing lengthy processes like touching files, accessing databases and such in the Dispose method.
Actually let's break this down a bit...
Disposing from the GC call to the Finalizer
When you implement the IDisposable pattern (not the interface, the pattern, finalizer and all) you are essentially saying that your object has an unmanaged resource that nobody else knows about. That means you have PInvoked a call to Win32's CreateFile, or maybe you called Marshal.AllocHGlobal or something like that. Essentially you likely have an IntPtr instance member you need to do something with to prevent a memory leak. These are the ONLY types of things that should be done when the disposing parameter is false (i.e. called from the finalizer on the GC thread).
Generally you DO NOT call the Dispose method on children. You should not expect any child object to be valid. Simply touching a member of the child object can accidentally 'revive' or resurrect it.
So when you are writing code that executes in a Dispose method called from the Finalizer you have to be careful. You are executing on the GC thread while the rest of your application waits for you. You should perform as few operations as possible to release the unmanaged memory/resource and quit. Never throw an exception and if you are calling an API that may throw you should catch any exception raised. Propagating exceptions back to the GC will prematurely abort the finalizer thread and the remaining objects to be finalized will not have a chance to clean up.
Disposing from the IDisposable.Dispose() method
As I’ve already said, using the Dispose method is safe enough and can safely accommodate any amount of code/process. This is where you would free unmanaged resources, call the dispose method of child objects, flush and close files, etc. Most of the Dispose methods I’ve written do not have an associated Finalizer and therefore do not follow the IDisposable pattern, yet they implement IDisposable just for the convenience of the using statement.
Am I wrong? Are those action's OK as long as you are handling any possible exceptions so they don't bubble out of the method? I just don't think doing a lot in Dispose is a good idea. I would like to know what the community thinks.
You are absolutely right when the dispose method in question is used from a finalizer. You’re assertions about what you should and should not do in a Dispose method should actually be reworded to apply to anything called by a Finalizer. The fact that this is generally done in a method called Dispose is a matter of convention, the IDisposable pattern, but these issues could easily exist in other methods used by the Finalizer.
If an object does something to the state of some outside entities in a way which makes them more useful to that but less useful to everyone else, the Dispose method of the object should do whatever is necessary to restore outside those entities to more generally-useful state. If one wishes to avoid having an object do too much work in Dispose, one should design the object so as never leave any outside entities in a state which would be onerous to clean up.
BTW, Microsoft likes to use the term "unmanaged resources", and gives examples, but never really offers a good definition. I would suggest that an object holds an "unmanaged resource" if an outside entity is altering its behavior on behalf of that object, in a fashion which is detrimental to other objects or entities, and if that outside entity will continue to alter its behavior until the object stops it from doing so.
You should lean toward the conclusion you have already come to. However there are situations where you need to ensure that services are stopped and that could include things like messages being logged for the service shutdown, or saving the current runtime state to data store. This type of disposal usually only applies to things that have a lifestyle that is application scope, meaning they exist the whole time the application is running. So there are situations outside of the expected norm. As is the case with every rule you should follow when writing code.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why does asynchronous delegate method require calling EndInvoke?
Is Delegate.EndInvoke() really necessary?
Working on a multi-threaded application at the moment and when raising an event instead of doing the normal handler.Invoke(); I am experimenting with handler.BeginInvoke();. Both work fine. However, for BeginInvoke I am using null for the last two arguments because there needs not be a callback and since there is no callback, there is definitely no need for data to be passed to a non-existent callback.
Because of this, I am not calling EndInvoke at all. But the application seems to.. work perfectly? I read and people said there would be leaks which may be occurring but I am just not noticing.
I'm curious though, what exactly does EndInvoke do? Do I really need to make a callback just to call EndInvoke and that's it? Also, why does EndInvoke take an IAsyncResult argument? I can just pass null for that right because there is no extra data being passed to the callback, correct? But still, I'm wondering, why, if there was extra data, would it need to be passed to EndInvoke? What is it doing with that parameter? I want to know how it works.
I checked the .NET Reflector but I couldn't find where EndInvoke was actually defined. In EventHandler (which is what I'm using) all it showed was the method header.
Thanks.
The main practical concerns are deterministically cleaning up a wait handle resource (if you chose to create the handle by referencing it) and making sure that Exceptions are propagated properly.
That said, what I would recommend is to move away from the slightly schizophrenic asynchronous pattern in the earlier .NET framework and use TPL, which has a much cleaner continuation model. The TPL even has some nice wrapping functionality to help deal with the older Begin/End style of calling:
http://msdn.microsoft.com/en-us/library/dd997423.aspx
As was mentioned in one of the referenced articles, if you're invoking a delegate in a fire-and-forget fashion, you probably should use ThreadPool.QueueUserWorkItem instead. Then you won't have to worry about cleaning up with EndInvoke.
According to MSDN, you ought to always call EndInvoke no matter what:
No matter which technique you use, always call EndInvoke to complete your asynchronous call.
So take that for what it's worth. I assume it's futureproofing.
I have a somewhat unusual scenario where I need to be able to outright slaughter "hung", self-hosted WorkflowInstance's after a given timeout threshold. I tried the Abort(), Terminate() and Cancel() methods but these are all too "nice". They all appear to require a response from the WorkflowInstance before they are honored.
In my scenario, a workflow entered an infinite loop and was therefore unresponsive. Calls to the normal methods mentioned above would simply hang since the workflow was completely unresponsive. I was surprised to learn the WorkflowRuntime does not appear have a mechanism for dealing with this scenario, or that Abort() and Terminate() are merely suggestions as opposed to violent directives.
I scoured google/msdn/stackoverflow/etc trying to find out what to do when Terminate() simply isn't going to get the job done and came up dry. I considered creating my own base activity and giving it a timeout value so my "root" activity can kill itself if one of its child activities hangs. This approach seems like I'd be swatting at flies with a sledge hammer...
Is there a technique I overlooked?
The only true solution is to consider this a bug, fix whatever went wrong, and consider the matter closed.
The only way to forcibly abort any code that is locked in an infinite loop is to call Abort() on the thread. Of course, this is considered bad juju, and should only be done when the state of the application can be ensured after the call.
So, you must supply the WorkflowApplication an implementation of SynchronizationContext that you write which can call Abort() on the thread that the workflow Post()s to.
I am not sure if this will work, but have you tried the WorkflowInstance.TryUnload() function? I remember this to fire off a few events inside of the workflow (been a while since I did this), so you might be able to have an event handler in your workflow that catches this and does a kill switch on itself.
I've read conflicting opinions as to whether every BeginInvoke() has to be matched by an EndInvoke(). Are there any leaks or other problems associated with NOT calling EndInvoke()?
Delegate.EndInvoke is documented as a thou shalt call this (i.e. necessary - else leaks happen) - from msdn:
Important Note
No matter which technique you use,
always call EndInvoke to complete your
asynchronous call.
Control.EndInvoke is OK to ignore for fire-and-forget methods - from msdn:
You can call EndInvoke to retrieve the
return value from the delegate, if
neccesary, but this is not required.
However - if you are using Delegate.BeginInvoke and don't want the result, consider using ThreadPool.QueueUserWorkItem instead - it'll make life a lot easier, and avoid the pain of IAsyncResult etc.
EndInvoke is not optional.
More info here
And EndInvoke call is not optional call, it is a part of the contract. If you call BeginInvoke you must call EndInvoke.
Classic example of why this is necessary. It's very possible that the IAsyncResult returned from BeginInvoke has allocated resources attached to it. Most commonly a WaitHandle of sorts. Because IAsyncResult does not implement IDisposable another place must be chosen to free the resources. The only place to do so is EndInvoke.
I briefly discuss this problem in the following blog post.
http://blogs.msdn.com/jaredpar/archive/2008/01/07/isynchronizeinvoke-now.aspx
EndInvoke is not optional because it is the place where exceptions are thrown if something went wrong in the asyncronous processing.
Anyway there should not be any leak because if the IAsyncResult is holding some native resource it should correctly implement IDisposable and dispose such resources when the GC calls his finalizer.
It is not optional because calling BeginInvoke makes use of a WaitHandle which in turns makes use of a kernel object that maintains a count for how many references are had to it. Calling EndInvoke gracefully disposes the handle which decrements that counter on the kernel object and when that count reaches zero, the kernel object manager will destroy it.
Its only optional if you don't mind your program's memory growing very large. The issue is that the GC is holding onto all of the references in your thread, because you might want to call EndInvoke at some point. I would go with Marc's answer, the threadpool will make your life easier. However, you need to watch out if you spawn threads from your threads, as it is limited in the number of threads it can spin up.
Every reply on this post says that EndInvoke() is not optional. However, I found the following highly ranked comment that is the accepted answer on this SO thread:
"Note that the Windows Forms team has guaranteed that you can use Control.BeginInvoke in a 'fire and forget' manner - i.e. without ever calling EndInvoke. This is not true of async calls in general: normally every BeginXXX should have a corresponding EndXXX call, usually in the callback."
What's the difference between Invoke() and BeginInvoke()