|
I have placed a timer on the silverlight page where every 10 seconds it calls a windows service for some data. Even with this architecture, don't you think a background worker is required. I know the call to the win service is asynchronous but with having a timer in the page should there be a background worker?
Thanks
|
|
|
|
|
The problem is you're calling an asynchronous operation in order to call an asynchronous operation... Allow me to illustrate...
Form: "Ok, I want you to check this thing every ten seconds, and just write the results on this chalkboard over here..."
Timer: "No problem!"
backgroundWorker.DoWork += backgroundWorker_DoWork;
* Timer goes back to his office...
Timer: "Alright, you there... When I ring this bell, I want you to go perform your task, and let me know how it goes."
BackgroundWorker: "You got it, boss!"
Timer: "Ready..... *ding*!"
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
* BackgroundWorker runs to his office...
BackgroundWorker: "Hey, I need you to check this service for me."
Client: "Um, ok, but it's going to take a while..."
BackgroundWorker: "Yeah, I don't care... Just go do it, ok?"
Client: "If you say so..."
* Client goes off to check on the service
e.Result = ??;
* BackgroundWorker goes back to Timer
BackgroundWorker: "Ok, all taken care of."
Timer: "Really? Already? I thought that would take a while."
BackgroundWorker: "Well, you know me."
Timer: "Right... So... uh... Did it all work out ok?"
BackgroundWorker: "Uh... yeah... sure... I mean, yeah, everything's great."
Timer: "Ok, good."
void client_GetDataCompleted(object sender, WinService.GetDataCompletedEventArgs e)
* Timer makes a note on Form's chalkboard
...Meanwhile...
* Client works on the job... Tick tock tick tock...
Client: "Ok, that took longer than I expected... Hey, BackgroundWorker, I have the results you wan-- Oh... You went home for the day... Uh... Anyone care? I'm done now... I mean, there were some problems, but... Anybody? Anybody at all? Oh well... Guess they didn't really want this Exception..."
(Sorry, I'm in an odd mood this morning...)
|
|
|
|
|
...can you do another one for me please?
Illogical thoughts make me ill
|
|
|
|
|
What the list thing over in C#? Not nearly as entertaining
|
|
|
|
|
haha, that post is getting too nodey. I like your teaching style thou.. can you do a version that explains why code behind in a WPF application View is bad while using an MVVM design pattern (I still don't see the logic)
Illogical thoughts make me ill
|
|
|
|
|
Ya know, I was never a big fan of strictly adhering to design patterns... I consider them guidelines, not rules.
|
|
|
|
|
musefan wrote: can you do a version that explains why code behind in a WPF application View is bad
It's not necessarily bad. It just depends on the code.
Here's an example that might help explain it:
You are running a company that makes the iWidget - it's the latest, greatest, MP3 player. Now, you outsource the actual manufacturing of the components to third parties (the ViewModel). Your job is to assemble them together (the View). Now, you want to have fancy, schamncy wizzing window effects. You could outsource this to the component manufacturers, but it actually makes a lot more sense in this case for you to do it yourself.
And there you have the delineation of responsibilities in MVVM - the VM does the logicy, commandy stuff, while the view does the view related stuff.
|
|
|
|
|
Hello Ian,
Could I please you to help me with my problem?
I have this code in big method in my Silverlight application that uses WCF service:
private void F()
{
DatabaseServiceClient client = new DatabaseServiceClient();
client.GetSubsystemsByTestRunIDCompleted +=
new EventHandler<GetSubsystemsByTestRunIDCompletedEventArgs>(client_GetSubsystemsByTestRunIDCompleted);
client.GetSubsystemsByTestRunIDAsync(testRunID);
treeAdditionalInfo.Items.Clear();
foreach (string subsystemName in lstSubsystems)
{
TreeViewItem subsystemItem = new TreeViewItem();
subsystemItem.Header = subsystemName;
subsystemItem.FontSize = 14;
treeAdditionalInfo.Items.Add(subsystemItem);
}
List<KeyValuePair<string, List<TestLogSmall>>> lstFormsAndActions =
client.GetFormsAndActions(testRunID).ToList();
client.GetFormsAndActionsCompleted +=
new EventHandler<GetFormsAndActionsCompletedEventArgs>(client_GetFormsAndActionsCompleted);
client.GetFormsAndActionsAsync(testRunID);
...
}
The code in first 2 callbacks is this:
private void client_GetSubsystemsByTestRunIDCompleted(
object sender, GetSubsystemsByTestRunIDCompletedEventArgs e)
{
lstSubsystems = new List<string>();
if (e.Error == null && e.Result != null)
lstSubsystems = e.Result;
}
private void client_GetFormsAndActionsCompleted(
object sender, GetFormsAndActionsCompletedEventArgs e)
{
lstFormsAndActions = new List<KeyValuePair<string, List<TestLogSmall>>>();
if (e.Result != null)
lstFormsAndActions = e.Result;
}
I need to get the list after this call:
client.GetSubsystemsByTestRunIDAsync(testRunID);
And to get the list after this call as well:
client.GetFormsAndActionsAsync(testRunID);
How can I do that? What should I write?
Thank you in advance.
|
|
|
|
|
I think you're a little confused as to the workings of an asynchronous operation. Here's what you're doing...
F: "Ok, client, I want you to go get all of those subsystem thingies."
Client: "Sure thing, boss... I'll be right back."
F: "Good, now let's put those subsystems in the tree--"
Client: "Hold on! I haven't even left yet!"
F: "Where's my list of subsystems?"
Client: "Give me a #(%*&#ing minute to get it!"
F: "Ok, I guess there aren't any... Now, Client... Oh good, you're here."
Client: "Of course I'm here... You haven't given me a chance to leave yet!"
F: "Now go grab all of those forms and actions, ok?"
Client: "Fine... But it's going to take a few minutes to--"
F: "Good, now let's put the forms and actions into--"
Client: "That's it! I quit! Get your own #(*%&#ing actions!"
Now, here's what you want to be doing...
F: "Ok, Client1, I want you to go get all of those subsystem thingies."
Client1: "Will do."
* Client1 goes off to do his job
F: "Great... Now, Client2, you're going to fetch all of those forms and actions."
Client2: "Yep, I'm on it, boss!"
* Client2 goes off to do his job
* F makes sure everyone is gone, and turns on the TV to check the latest scores...
* Client1 and Client2 both return
* Client1: "All done. Here's the results."
* Client2: "Me too... Here's mine.
* F turns off the TV, grumbling about how he has to actually do some work
* F: "Alright, you first... Let's put these things in the tree......"
So you see, when you send the clients off to do something, that's called an asynchronous operation... Because they can do something on their own, and you don't have to sit there waiting for them to finish. Sending them off is your RunAsync() operation, whatever you want to call it.
The trick is that you're trying to read the results as soon as you send them away, instead of doing that after they come back. When they return with the results, that's the "GetSubsystemsByTestRunIDCompleted" event, in your example. THAT's where you should be processing the resulting data... In the handler for that event.
|
|
|
|
|
Ian,
Thank you very much for your answer.
I've understood Silverlight programming model was different than WPF.
If I understand you correctly, it's not possible to do the thing I need?
If so, it's not so good. My method is fairly long and complex. And the things are going in the loop as well. So, if I need to rearrange all these things, hm...
Is there any way to overcome this async style of doing the things?
|
|
|
|
|
Not directly know, and it is bad practice to consider doing it. You would, potentially, have to leave a long running connection open to a web server which would put a strain on resources.
Honestly, this is why desktop people shouldn't be writing web applications - the two disciplines are just too different.
|
|
|
|
|
Please don't hijack somebody else's thread. That's just impolite.
|
|
|
|
|
Hello,
I don't think it's impolite. It's normal communication between people. But, in any way, I won't do that in the future.
Regards,
Goran
|
|
|
|
|
It's not good form. The whole point of a threaded question is to answer the original posters problem, not to introduce something confusing into the mix. You have added nothing, other than a distraction, to the posters knowledge.
|
|
|
|
|
Again, not specifically WPF but ...
Most of the MVVM frameworks implement some sort of Messaging pattern to allow ViewModels to communicate.
Say VM1 selects a customer, it sends a "Customer Selected" message and VM2 responds to that message by displaying that customer's details.
All (that I have looked at) use a singleton Messenger object (the name varies) to which every VM has access and can subscribe to Messages or send messages.
And it all works fine and dandy.
Here's the bit I don't understand.
would it not be just as easy (if not easier) to use events? Isn't this just what the messenger is duplication?
So VM1 selects a customer and tells an "Eventor" singleton to raise the "Customer Selected" event. VM2 has subscribed to this event, and so displays that customer's details when it is raised.
I feel sure that there's a good reason for not doing this, but I'm stuffed if I can think what it is?
(Just to show I'm not a complete doofus, I am aware that most Messenger implementations avoid potential memory leaks by using WeakReferences, which may be an advantage - but is that the only reason for using it?)
Thanks
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
_Maxxx_ wrote: (Just to show I'm not a complete doofus, I am aware that most Messenger implementations avoid potential memory leaks by using WeakReferences, which may be an advantage - but is that the only reason for using it?)
No, that's not the only reason - in fact, routed events use weak references internally as well.
_Maxxx_ wrote: I feel sure that there's a good reason for not doing this, but I'm stuffed if I can think what it is?
Decoupling. Purely and simply, decoupling. With event subscription you create an implicit hard relationship between the subscriber and the subscribee, so your ViewModels end up having knowledge of each other, which makes testing much more problematic. If you accept that one of the key tenets of MVVM is increasing testability then you see that having a mechanism that allows you to mock out the source of the "event" makes it much easier to test the VM.
I hope that helps.
|
|
|
|
|
I posted my question 7 minutes ago and still don't have a reply! send codez plz!
Wow - quick reply - thanks Pete...
Pete O'Hanlon wrote: . With event subscription you create an implicit hard relationship between the subscriber and the subscribee
true - but in my scenario the VM dosn't raise an event - it tells another (singleton) object (the equivalent of the Messenger which I called Eventor) to raise the event - so the only hard relationship is between VM and Eventor.
Pete O'Hanlon wrote: If you accept that one of the key tenets of MVVM is increasing testability
I do - and maybe that's where my knowledge is failing, as I haven't got my head around TDD yet.
Pete O'Hanlon wrote: having a mechanism that allows you to mock out the source of the "event" makes it much easier to test the VM.
Any reason why I can't mock something that raises an event just as easily as mocking something that sends a message?
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
Message/Event. It's up to you how you want to do it. A message is a lighterweight method of communication, so that's why it's popular. Have a look at what Marlon and I did in MefedMVVM[^] to see how we used a drop in Mediator for VM communication
|
|
|
|
|
Pete O'Hanlon wrote: Message/Event. It's up to you how you want to do it.
Ahhrghhh - don't tell me that! I want to be told "this is the best way to do it!" Now I need to go look at more stuff!
Pete O'Hanlon wrote: lighterweight
Some sort of boxing terminology?
Pete O'Hanlon wrote: Have a look at what Marlon and I did in MefedMVVM[^]
Noooo - more frameworks?!
Seriously, though, thanks for the help. I'm getting there.
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
Personally I try to avoid messages.
Yes, it gives a view model that is easier to write tests against, but it does it at a cost:
1) The compiler (and refactoring tools) are unaware of messages. Basic errors normally displayed at compile time are now runtime errors.
2) When debugging, the event's are typically delivered without any stacktrace showing where the call came from (at least in the toolkit I have been forced to use) making simple debugging operations complex.
Personally I find the price too high and I avoid using the messages. It would be nice if we could get weak event subscriptions though.
|
|
|
|
|
lmoelleb wrote: 1) The compiler (and refactoring tools) are unaware of messages. Basic errors normally displayed at compile time are now runtime errors.
That depends on the message type. If you use an enumeration for the message, then you get compile time checking. Yes, string based messages are prone to code smell.
|
|
|
|
|
Pete O'Hanlon wrote: string based messages are prone to code smell
Ah so now I have stinky code huh. I got the impression that Silverlight does not like enums, I think they did not cross from VM to View or something.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
It can't be Silverlight per se - must be whatever MVVM Framework you're using. After all, an enum is just an integer by any other name.
Personally I was thinking (if I use messaging rather than events) of using a message class rather than a string- although the overheads of defining a class for every message seems like overkill to me...
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
_Maxxx_ wrote: It can't be Silverlight per se
I think it is SL as I ran across some issues trying to parse an enum in the code behind of a view and dropped enums from the SL app for this reason. I can't remember the details so I will have to do some more investigation.
Prompted by Pete's comments I will now spend some more time with enums. B/C of delivery pressures I tend to drop a problem issue for later investigation if there is a Q&D work around (strings fitted this area).
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
A few things I didn't see mentioned in responses:
1) In *proper* 100% by the book mvvm, ViewModels shouldn't known about each other. With that being said, how could they subscribe to events?
2) You could put all your message types in a central place for convenience. Or make static public members. Same thing. There are pros and cons to both.
3) I've never seen a messenger class with weak references. What framework was that in? Usually they do something like Messenger.GetMessage(messageType).Subscribe(callback) or Messenger.GetMessage(messageType).Handler += callback.
The one I wrote doesn't use weak references, but it handles "bad" handlers by removing the subscription. I think thats a bigger concern then mem leaks. Also, async is a big deal. No point in calling one callback and waiting for it to finish (most messenger classes I've seen do this!) before calling the next.
|
|
|
|
|