|
_Maxxx_ wrote: Do you think the VM with no references responds to the message? The VM with no references? Yes - it Does! Even though I'm only accessing it via Weak references, and there are no real references to it, it has not been garbage collected .
That suggests that you actually have a strong reference to it rather than a weak reference. Remember that a weak reference does not guarantee that a strong reference will not be taken, or that the reference will be downgraded back to a weak reference afterwards. This is one of the reasons that my implementation of the mediator provides a method to dereference messages.
|
|
|
|
|
Pete O'Hanlon wrote: That suggests that you actually have a strong reference to it rather than a weak reference.
That's what I thought - but using ANTS there are no strong references - indeed if I do a GC.Collect then it "goes away" entirely and the problem is no linger a problem
The problem seems to me to be that, after an object is ready for garbage collection, it may or may not be collected at any time - the GC doesn't actually collect it until it needs some memory (or you force it to garbage collect)
Having to dereference messages when a VM is finished with strikes me as as bad a problem as remembering to remove event handlers - and just as hard to track down problems!
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
As Pete said, why bother with weak references here? A VM who doesn't unsub from the messenger events is being kind of douchey, wouldn't you say? Don't confuse WeakReferences with bad programming . I guess its good to be able to handle bad code.
Anyways, in answer to your real question, WeakReference has the IsAlive property that you can use.
EDIT: As a side note, I've often found WeakReferences to be trouble prone... cuz a douchey / lazy developer might do:
Whatever.Blah = new SomeObject();
Guess what happens here? Blah is a WeakReference behind the scenes and the new SomeObject() goes out of scope immediately and gets GC'ed because there was no strong reference to it .
|
|
|
|
|
SledgeHammer01 wrote: As Pete said, why bother with weak references here? A VM who doesn't unsub from the messenger events is being kind of douchey, wouldn't you say? Don't confuse WeakReferences with bad programming . I guess its good to be able to handle bad code.
I guess I was thinking that using the weak references and messages rather than events would get around the issue of programmers forgetting to remove event handlers across objects when the object is finished with.
If you still need to remove your registration from the messenger, then I'm not sure what the advantages of messaging over eventing are.
It is actually obvious when you think about it, but the issue I am having (where the object is ready for GC but has not yet been GCd, but the objects is still available due to a weak reference somewhere) is as dangerous as all hell.
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
The IsAlive property gives you some safe guards, but there is still kind of a race condition. WeakReferences are only there so you don't lock an object from getting GC'ed (duh), but as Pete explained, its easy for an object to go back and forth between weak only and weak & strong. Also, in the example I gave you, its entirely too easy to completely defeat the purpose of weak references because if your object is init'ed inline like that, it'll get GC'ed right away and you'll be debugging code for hours. In that case, you'd need to keep a strong reference to it anyway.
I remember working on a piece of code, I forget what it was right now, but it was something related to commanding & event handlers in some part of .NET (buttons I think). Anyways, I subbed to an event and couldn't for the life of me figure out why the event handler was only getting called once.
Turns out Microsoft had decided to use a weak reference for that particular thing and:
blah.whatever += new EventHandler(...);
was getting GC'ed right away (the event handler I mean was getting GC'ed).
I had to save a strong reference to the event handler in my class. I thought that was really ugly.
Best to avoid weak references IMO. They are often tricky to debug when you forget they are there and just kind of serve as a band aid for sloppy programming.
If a view doesn't unsub from something and causes a leak, why not fix the view rather then hide the problem?
|
|
|
|
|
SledgeHammer01 wrote: If a view doesn't unsub from something and causes a leak, why not fix the view rather then hide the problem?
COuldn't agree more!
S'funny. I started off a while ago asking about why people use messages rather than events - I mean my ViewModel can subscribe to an event raised by another "some singleton object" in response to a request by a ViewModel
I didn't get the difference between that and the situation where my ViewModel can subscribe to a message sent by "some singleton object" in response to a request by a viewmodel.
The difference as I understood it was allowing weak references to be used - but that's really only an advantage I think if you subscribe from one VM directly to an event raised by another VM - rather than some singleton...
I feel lI must be missing something, and perhaps need to go back and read the various articles about this - because I'm back to squeare one again now - thinking I may as well use familiar old events
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
SledgeHammer01 wrote: WeakReference has the IsAlive property that you can use.
Unfortunately you're mistaken The IsAlive property tells you if the object has been garbage collected - not if it is ready for Garbage Collection - so my problem persists.
What I think is needed is a "int TheIbjectReferencedByThisWeakReferenceHasThisManyHardReferences" property (or a bool with HasAnyHardReferences) At least that way I can see that as there are no hard references, I should not use the object (as the GC really should be cleaning it up) and should probably delete my Weak reference.
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
Hi,
I need to develop a KIOSK application in dotnet technologies, like WPF, Silverlight, Expression Blend etc. But I have no idea on how to start this. If you have worked on this, could you share your experiences please? Any sample code provided will be much appreciated.
Thanks in advance,
nishant
|
|
|
|
|
if you've not really programmed on WPF / Silverlight before, you migth want to start with some videos / tutorials on msdn or other websites.
The funniest thing about this particular signature is that by the time you realise it doesn't say anything it's too late to stop reading it.
|
|
|
|
|
Member 3657007 wrote: But I have no idea on how to start this.
The best starting point would be to buy a book and look at some of the articles here on CodeProject. However, unless you have a reasonable level of experience in C# or VB.NET you have a long learning path ahead of you.
I must get a clever new signature for 2011.
|
|
|
|
|
I have done quite a lot programming in C#. I just wanted to know about developing kiosk applications. Anyways thanks for your response.
|
|
|
|
|
Member 3657007 wrote: I just wanted to know about developing kiosk applications.
Did you try this[^]?
I must get a clever new signature for 2011.
|
|
|
|
|
I've been using the Mediator pattern for a while in MVVM - specifically using the MVVMFoundation implementation mostly.
So this pattern allows you top broadcast a message that can be subscribed to by one or more classes (usually ViewModels) and handled by them.
What I am trying to do at the moment is extend this pattern as follows (an example is worth 1K words)
Customer Lookup allows user to select a customer, and will open an 'Edit' window for that customer. The window is not opened modally.
The user, then, can select the same customer again for editing (because the user is daft).
So I would like the Customer Lookup Vm to send out a 'This customer has been selected' message, to which the Customer Edit VM would subscribe.
If , as a Customer Edit VM I receive the message, and I am currently editing that same customer, then I can take some action (show a 'Silly User' message for example).
If I receive the message and I am not editing that same customer, I can ignore the message.
But if the message is sent and ignored by all VMs out there (because there isn't one editing this particular customer) then I need to get a new Customer Edit VM created to go edit this customer.
Now, I'd like to do this reasonably generically, so I started looking at the Messanger class, to see if I can't add to it, to enable 'IsHandled" type properties. And it works well.
Except!
My Customer Lookup is the first VM instantiated, and so is the first Vm to register to receive the message - and so handles it immediately - without giving he other ViewModels a chance!
Obviously, sending the messages is handled in a loop - so I could reverse the order - but it may not be the last instantiated View Model that I want to handle a message.
Or I could add a 'priority' to the message registration process - and sort the responses in priority order, so that my Edit VMs see the message first.
Or, I could change the messaging into a two-step process - the first stage asks who can handle the message, and the second stage decides who to give the message to.
I guess what I'd like is to hear some discussion on this. Have you done something similar (is there some code out there I can steal look at for inspiration? Have you overcome similar problems some other way?
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
Sounds like you would need a blocking "broadcast to everybody but x" and if e.Handled = false afterwards, send to x. Listener registeration is in indeterminate order, so you can't really depend on order to know who the fallback listener is.
|
|
|
|
|
If customer lookup is VM that is raising the message, why is it subscribing to it? The whole point is to allow disparate VMs to communicate with each other, so the originating VM doesn't need to be a listener. Perhaps I have misunderstood your scenario, but it seems like the fix is to remove the listener from the originating VM.
|
|
|
|
|
Hi Pete
The issue is (and bear in mind this is not a real application as yet):
If my VM Customer Lookup sends a message out to say "HEy, the User just selected Customer 123" then something needs to handle the message.
I possibly have not yet instantiated a Customer Edit VM, so don't know if there's anyone out there listening for the message.
My idea was to send the message, then if nobody handles it, handle it myself by getting a CustomerEdit VM instantiated to edit this Customer.
So the only reason the listener is there in the lookup is to handle the instantiation of a VM to handle the event.
I could (of course) have the VM keep a list of all the CustomerEdit VMs it has had instantiated, and compare any new selection against that list, only instantiating a new one should I need to - but that would require my Look UP VM having references to all of the Edit VMs.
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
No it doesn't. The change you need to make to your messenger class is to see if there are any listeners for that message. Presumably it's in a dictionary internally, so all you need do is check the count of references against that message and react accordingly. In fact, that's such a useful modification that I am going to change my implementation accordingly. Thanks for the idea.
|
|
|
|
|
I don't know how to express my gratitude. It's so obvious now I don't know how I didn't think of it!
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
Actually, I owe you gratitude. I didn't think of doing this, but now that I've put it in I can see how useful it is. You gave me the inspiration, so thank you.
|
|
|
|
|
Well, you know what they say about Inspiration and Perspiration...
Incidentally, I am also passing a Message object around with my messages. This object (amongst other things) allows each Message handler to report whether it has handled the message (and gives it the option to stop the message being sent to any other handlers.
so my implementation rather than returning an effective boolean, returns
MessageHandled,
MessageNotRegistered,
MessageAborted,
MessageRegisteredNotHandled
So , for example, I can send out a message to perform some action, but all of the potential handlers may be too busy, so I get a MessageRegisteredNothandled return value.
This is very much a work In Progress, so I haven't worked out all the ins and outs, but it seems to solve some of the potential issues I was worrying about.
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
_Maxxx_ wrote: MessageAborted,
That's interesting. Something I've been struggling with myself for a while is whether the Mediator should wrap exceptions up, or just fail at the first instance. There are arguments for and against this, and I've been toying with the idea that the mediator should have a WorkResult object which includes this information. If I do this, then the status would be the enumeration, and the exceptions would be stored in there as well.
|
|
|
|
|
Great minds ... etc.
When I started looking into this sort of thing, the problems started to grow. For example, if a Message Handler throws an exception, and catches it, then stores it in the WorkResult object there are two choices - the Mediator aborts as soon as one handler throws an exception, or it continues to try any other handlers - and if they throw exceptions, do you start keeping collections of the damn things?
If the mediator itself gets an unhandled exception, then returning it to the sender might be a good idea - but then why not just leave it unhandled? it is, after all, an exception?
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
Well, I've changed my implementation and I'm busy testing it out now. The reason I've been toying around with this idea is that in some cases I've wanted to have some VMs continue processing even when one has failed due to a SQL exception because I can handle this later on. This change could be useful.
|
|
|
|
|
It'll be interesting to see how it works out.
In these sort of cases are you trapping the exception in the VM and adding the info to the Mediator object, or do you leave the exception for the mediator to trap and log?
The reason I;m looking at all of this right now is that I'm writing an article (I say AN article, it's likely to be a series of about twenty the way I'm going!) about they way I'm doing MVVM
As usual with this sort of thing, as soon as I start to describe the whys and wherefores, I think of additional things I'd like to do, and the whole thing expands and expands...
The good thing is that I end up with a good, well thought out "framework" - I just will have to draw the line in the sand somewhere!
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
_Maxxx_ wrote: In these sort of cases are you trapping the exception in the VM and adding the
info to the Mediator object, or do you leave the exception for the mediator to
trap and log?
It really depends. I'm a great believer in trapping and handling errors where you can. In some cases though, I want the exception to bubble upwards - but because of the loose coupling between the VMs, I want to still allow the others to continue. In this case, the result is acting almost like a mediator message in its own right - the mediator becomes aware of the exception, but it can still continue.
|
|
|
|
|