> Or you may want to take a look at Microsofts asynchronous application
> block

I've spent an hour or two sort of looking through the code for this, but
haven't got too heavily involved with it. I guess the reason I didn't
get to stuck into it is that I don't really want asynchronous
processing. I just need it to keep my UI alive while I do synchronous
processing.. 

Also, I'm particularly interested from the point of view of 'in-process'
rather than out-of-process or across the wire processing. I'll have a
closer look though, now that you've bought it up.

> >> multithreaded MVC in WinForms
> 
> MVC (Model View Controller) comes from Smalltalk and is a pattern for
> decoupling view, controller and application model. In ASP.NET for
> example the code behind file is the controller, .aspx (with only
render
> code) is the view and the model is what ever you want it to be. Often
> the controller and view are implemented as the same class - WinForm
> implementation
> Another pattern usually used with MVC is the observer
> (publish/subscribe) pattern which enables the model to inform the
views
> of changes. When used with MVC the model is the subject and the view
is
> the observer. The observer provides an implementation of an Update
> function which the subject then calls. So, the idea is when the model
> changes any views subscribed will be notified via their Update
methods.
> This pattern was used in MFC (yuck!) - may remember it being called
DDX,
> DDV.
> 
> Some catalogues say that the Update method of the observer should
accept
> a subject as one of the parameters. Whilst I don't disagree with this
I
> do think it can be misleading. In a multithreaded environment it could
> be a potential disaster to pass a reference to the model (the
subject).
> An alternative to passing a reference to the model is to use a push
> replication strategy. Here the model calls Update of the observer, but
> passes the 'changed' data 'by value' (a message). The view can then
> decide which bits it needs. This is easier than a pull model
(reference)
> where the view would have to go get the data from the 'thread-safe'
> model

Yep. I understand and agree with your explanation here. Passing state
isn't feasible for two reasons: 

A. there could be *lots* of state, and cloning it 'just in case' for
every message is just not an option
B. state may not be available.

You're right in saying that I can't pass a reference to the model
because of the locking problems (or complexities), i.e. deadlocks,
blocked UI, or bogus data.

An example of B would be if I had code that specified:

this.Project.ClientId = 42;

This could cause a Project.ClientChanged event. When this event is
handled by an interested view, it might want to do something like this:

this._clientNameTextBox.Text = this.Project.Client.Name;

or perhaps:

this._clientControl.Client = this.Project.Client;

since all that has happened in the client application is that the
project's ClientId has been specified, I would need to 'load' Client 42
by requesting it from the application server. I don't want to load the
Client if no view is going to want it (the view might only want to
specify this._clientIdTextBox.Text =
this.Project.ClientKey.Id.ToString(); for example) but I need to be able
to load it if it is required. But I don't want to load it on the UI
thread where the view is being updated.

So for this reason, neither of the two solutions above really suite what
I want to do, given this don't-block-the-UI-thread requirement.

My intended strategy for dealing with this is have the view then queue a
request for data, so the application thread will get it when it next
works on the model. In turn the application thread will need to alert
the view that the data is now available by queuing the event for when
the UI thread next gets to read from the model. This alert is an
implementation detail, I could throw the ClientChanged event again, or
throw a ClientLoaded event, or a RelatedDataLoaded event with an enum,
or whatever, the point is that getting the data is not explicitly done
by the view, getting the long-running code off the UI thread.. but like
I said, I haven't got an implementation yet, and am really just looking
for some direction on how to go about this.

> > I'm entertaining is that rather than invoking the events, I just
> > >stash the event delegates on a FIFO queue and then dispatch them
all
> > >once the worker thread returns (in the UI thread on EndInvoke for
> 
> Combining delegates together would give you this functionality. If you
> define your delegate with byRef parameters each delegate will be able
to
> modify the data. This is quite useful if you need to pass data from
one
> method to another in a chained manner (synchronously) - chain of
command
> 
> > >    this.Name = GetNameFromWebService(this.Id);
> > >    this.Phone = GetPhoneFromDatabase(this.Id);
> 
> Never, never do this type of stuff in a distributed application - if
> you're an OO purist I apologize, but put simply don't extend OO
thinking
> when it comes to remote communication.
> Fine granular calls like this are the killers are all applications
(okay
> blame RPC!), but if you take the same thinking that good OO design
means
> lots of getters and setters - forget it. It won't scale. In remoting
> situations we place a course grained interface 'remote façade' onto
the
> remote object. This interface has methods like GetPerson, SetPerson
etc
> 
> I know this is just an example that you're using (so I don't mean to
> rant at you personally ;-)

Heh, just to remove any lingering doubt: I was simply trying to
fabricate a reason why I might have a NameChanged and PhoneChanged event
triggered synchronously in a long-running operation. There is no way
that I would go across the wire for just a simple property like 'Name'.
:P

But I am happy to use blocking calls (RPC) to get the data that I need.
If you think about the implication of the queued system that I discussed
in my last post I could actually use this to my advantage to limit my
round trips. If 'load requests' were added by the UI thread, then when
the application thread gets a chance to service the 'command queue' it
might be feasible for it to look through the command list and process
all Create/Update/Delete commands first, then dispatch all Retrieve
operations to the application server in one hit. They all need to be
serviced, and they all need to return data before other processing can
continue, so they might as well all be serviced at the same time. Of
course, meddling with the 'order' of commands (i.e. altering the FIFO
order) might be bad for some reason that I haven't completely thought
through yet (if subsequent operations are going to require that data for
example).. at the very least Retrieve operations that weren't separated
by other commands could be packaged into one request..

John.

===================================
This list is hosted by DevelopMentor®  http://www.develop.com
Some .NET courses you may be interested in:

NEW! Guerrilla ASP.NET, 17 May 2004, in Los Angeles
http://www.develop.com/courses/gaspdotnetls

View archives and manage your subscription(s) at http://discuss.develop.com

Reply via email to