Control.Invoke uses SendMessage internally and Control.BeginInvoke uses
PostMessage.

Regards

Richard Blewett
DevelopMentor

> -----Original Message-----
> From: Moderated discussion of advanced .NET topics. [mailto:ADVANCED-
> [EMAIL PROTECTED] On Behalf Of John Davis
> Sent: 01 March 2004 11:48
> To: [EMAIL PROTECTED]
> Subject: Re: [ADVANCED-DOTNET] Thread with message pump (UI thread)
> 
> Yes, Control.Invoke uses the message pump.  The message pump is the queue
> you speak of.  I'm guessing the mechanism uses a PostMessage with a
> WM_USER
> + x.
> 
> ----- Original Message -----
> From: "John Elliot" <[EMAIL PROTECTED]>
> To: <[EMAIL PROTECTED]>
> Sent: Monday, March 01, 2004 5:34 AM
> Subject: Re: [ADVANCED-DOTNET] Thread with message pump (UI thread)
> 
> 
> > > If the UI never accesses the model directly (which would require
> > locking
> > > to avoid possibly getting inconsistent data if the model is in the
> > process
> > > of being updated), but only sends requests (via BeginInvoke) to the
> > model
> > > thread for information, does that solve the problem?
> >
> > I'm not sure that you can 'BeginInvoke onto the model thread'. As I
> > understand it (please correct me if I'm wrong), if I have a delegate I
> > can call BeginInvoke and it will be serviced by a worker thread from the
> > thread pool. I'm not sure that a 'worker thread from the thread pool' is
> > synonymous with 'model thread'.
> >
> > There are some gaps in my understanding around this however. For
> > example, how is it that Control.BeginInvoke allows the delegate to find
> > its way into the code path on the UI thread? The delegate must be added
> > to a queue and serviced at some point right? Which queue? Does it use
> > the message pump? If so, what sort of message does it send? Where can I
> > read about the mechanics of Control.BeginInvoke?
> >
> > The way I'm trying to think about it at the moment is that I have two
> > main threads. The 'UI thread' and the 'application thread'. The UI
> > serves two purposes:
> >
> > 1. Represent the model (view)
> > 2. Command the model (controller)
> >
> > My goal is to keep the UI as free as possible, basically the only
> > reasons for this are so that it can paint, respond to user requests that
> > don't rely on the model, or to 'cancel' something that is in progress.
> > It seems that a massive amount of work needs to be done to achieve these
> > relatively humble goals.
> >
> > The reason that this is hard in my particular case is that I have an MDI
> > WinForms application that shares data from a local (in-process) 'model'
> > of the data from the database. I don't use Dataset etc. because I run
> > into all sorts of trouble with a user fighting *with themself* over read
> > locks (i.e. timestamp/rowversion), defining complex relationships
> > between data that hasn't been allocated a primary key, etc. I use my own
> > business objects and collections to help me manage these relationships,
> > basically I'm building my own object-relational wrapper that is the main
> > component of the 'Model' in my MVC application.
> >
> > There are a few hairy design challenges. I want my model to be equally
> > usable in both a web based and WinForms based application. It gets
> > pretty challenging though, because the 'model' is designed for 'client
> > side' representation of data (I have a stateless application server that
> > can service requests and commands to populate the client-side model or
> > persist it to a data store) and these two execution contexts are quite
> > different.
> >
> > In a web based app, multiple users share a process, and if two users
> > were editing the same domain object (say, Employee, Invoice, etc.) then
> > I'd let them do it, and fail with an optimistic concurrency error ASAP
> > (to avoid them wasting their time). A web based app is largely
> > request-response, and so is simple in this regard. The user takes a read
> > lock (in the virtual, optimistic concurrency sense) on a 'smallish'
> > amount of data and then submits changes to that data, assuming there has
> > been no resource contention during the period that they were editing the
> > data I can just apply their changes, otherwise I can take them into a
> > 'merge' process (heh, or fail them ;). Obviously, pessimistic
> > concurrency has a whole heap of problems (particularly with a web based
> > system) so I choose optimistic concurrency as the lessor of two evils.
> >
> > But an MDI WinForms app is quite different because it offers a more
> > sophisticated UI. In a windows based app, if I have the same domain
> > object open in two views, and I alter one view, then I don't want:
> > A. the other view to continue displaying stale data
> > B. the user to have a concurrency problem when they flip to the other
> > view later and make an edit (to the now stale data)
> >
> > I'd really like my business model to be resilient in the face of
> > 'disconnection' too. So a user can carve off some existing data, enter
> > new data, specify complex relationships, and pump it all back into the
> > live system much later. I'd like to get as much support for this into
> > the business model (and related APIs) as possible, but this is largely
> > beside the point at the moment.
> >
> > I've already dealt with a lot of these problems, and I'm pretty happy
> > with what I've got (it's too complex for me to really go into via this
> > e-mail).
> >
> > I would describe what I have client-side in my MDI WinForms application
> > as an MVC application. I know that people argue about what MVC is, and
> > have different ideas about it. The scope of the problem that I'm trying
> > to describe here though, is that given this 'static' client-side model:
> > reading from it, updating it, etc. is all (relatively) straight forward
> > if all my processing happens synchronously on the UI thread. The problem
> > is that the UI thread is not free to respond to the user or paint itself
> > while it is processing, such processing pretty much always involves
> > going over the wire to the application server with blocking requests for
> > state or commands to change state (basically the CRUD).
> >
> > One of the particularly challenging problems is that 'View' code often
> > needs to do more than just 'read' from the model, often it needs to
> > 'load' data into the model, and this is a long-running process.
> > Lazy-loading isn't an option if I don't want to block the UI thread, and
> > really is 'programming by side-effect', because I can affect the state
> > of the model by doing a read operation. Design challenges are further
> > aggravated by security, caching, etc.
> >
> > At the moment I'm really looking at how I can use a different kind of
> > messaging paradigm between the Model/View/Controller than I presently
> > have. At the moment such messages are passed using multicast delegates
> > (AKA events). The crux of the problem with this type of notification is
> > that the message is sent synchronously as it happens. So, I'm leaning
> > more towards a client/server type of messaging system (more like
> > publish/subscribe than 'observer' if it's fair to try and make such a
> > distinction) where I can queue the multicast delegate for invocation
> > later, rather than dispatch it immediately.
> >
> > What I'm finding is that I now need to maintain 'message and command
> > queues' that are serviced on the appropriate thread. For example, if
> > code executing on the 'application thread' causes a change in state to
> > the model that a view has registered interest in (by attaching an event
> > handler) then rather than synchronously invoking the event so the view
> > can be updated immediately, I'd like to place this event on a queue so
> > that once the processing on the 'application thread' runs to completion
> > and the model is returned to a 'consistent' and 'not-locked' state I can
> > dispatch all the messages on this queue on the UI thread and let the
> > View objects request the updated state from the appropriate parts of the
> > model (with no fear of the model either being locked or in an invalid
> > state). Interestingly, it seems that I also need a queue for queuing
> > long-running commands (like 'Save') triggered by the user (or an event)
> > on the UI thread for processing on the application thread. Then I need
> > some form of mutex that ensures that either the 'controller queue' is
> > being serviced XOR the 'view event queue' is being dispatched. Meaning
> > really that either the UI thread is reading from the model, or the
> > application thread is updating it, but neither can attempt to run at the
> > same time. On the face of it, this seems like the best way to go at the
> > moment, but perhaps this is a crazy idea?
> >
> > > The UI thread will update the display using information passed in
> > event-
> > > handler parameters (as you indicated was a possibility), or it can use
> > > BeginInvoke to send a request for model state to the model thread and
> > uses
> > > the results that (eventually) come back to update the display.  (The
> > > latter could happen if the user pressed a Refresh button, or expands a
> > > tree node whose contents only exist in the model, or some such.)  If
> > the
> > > user does something in the UI that should cause an update to the
> > model,
> > > the UI thread uses BeginInvoke to pass the "update model" request.
> >
> > The 'pass state with event args' problem is interesting. Initially it
> > seems like this might be valid, but after a while you realise that (as
> > Shawn pointed out in his last post on this thread) you really need to
> > 'clone' state objects that are not strictly 'atomic' or 'immutable' when
> > you do this. Once you start adding any degree of complexity, then this
> > can get completely out of control and you might have to clone thousands
> > of objects just so you could send a Client.ProjectChanged event. If it
> > was just Client.NameChanged I might be able to pass a string with the
> > new name in the event args, but if the 'property' that changed was a
> > related business object then I might have to clone it (and everything
> > that it contained) just to pass the event. If the UI then wanted data
> > from this cloned Project that had not yet been loaded, it would have to
> > query the application server for that data. Basically my entire goal is
> > to 'avoid cloning, at all, ever' on the client-side, because it can
> > really hurt the working set, but more particularly because once I clone
> > I have one user with duplicate read locks on the same data that they can
> > cause to become stale. My other goal is to 'avoid locking, at all, ever'
> > because saving myself from deadlocks is non-trivial, locking decreases
> > performance, and I can still end up blocking the UI thread. Usually the
> > solution to avoid one is to do the other, but I don't want to do either.
> > Like I said, I want to have my cake and eat it too! :)
> >
> > The only way that I can see to accomplish this, is to have a 'turn
> > based' system, where the UI thread has a go at reading changes, painting
> > itself and queuing commands, then the application thread has a go at
> > processing the command queue, updating the model and queuing
> > notifications for the UI. The UI can still do 'stuff' while the
> > application thread is executing, but it must guarantee not to touch the
> > model. I haven't hit the point where this gets unreasonable yet, but so
> > far it's only in my mind (no concept code or anything like that) so
> > there may be some complexity that this introduces that is beyond my
> > ability to address that I haven't stumbled across yet (if there is, it
> > will most likely be with the 'controller' side of the problem, because I
> > haven't had a close look into that yet).
> >
> > The reason that I need a 'client-side' model is that I don't want
> > 'temporary state' to be maintained on behalf of clients by the
> > application server. Say I have a scenario where I'm entering a new
> > 'Employee'. I client the 'Create new Employee' button, and up pops a
> > form. Behind the scenes there some code specified 'new Employee();' as
> > the data source on this form. The user enters the name etc, but wants to
> > add an 'Address' for the residential address. Given that the residential
> > address is now not going to be 'null' I create a 'new Address();' and
> > assign it. Now I'm starting to have complex 'temporary state' in the
> > client that will need to be persisted by the application server inside a
> > single transaction. If I then specified that this employees postal
> > address 'was the same as their residential address' I might do something
> > like this: this.Employee.PostalAddress =
> > this.Employee.ResidentialAddress; Now things are getting even tougher,
> > because not only have I got complex relationships that I need to model
> > without primary keys that will later be specified by application server
> > (or the database) but I also have to represent this change to the user
> > in the user interface. So, if I had two 'AddressControl' instances that
> > represented the Residential and Postal address for this Employee on the
> > 'EmployeeControl' then if I changed the residential address I'd want to
> > see this change reflected in the postal address control. This is a
> > simple (and perhaps silly example) but it outlines the complexity that
> > I'm trying to model, and should serve to demonstrate why I can't
> > maintain the 'model' on the application server as easily as I can on the
> > client.
> >
> > Anyway, that's my rant for the day. At the end of the day the way I look
> > at it is that the MVC pattern (or perhaps I should say 'observer' or the
> > event-driven paradigm) is as old as time, async programming is as old as
> > time, and what I want is some good material where someone discusses
> > methods of integrating the concepts of each. I don't really want
> > asynchronous execution, what I really want is a method of keeping my UI
> > responsive while I work on shared local data, it's just that async
> > programming seems to be what I need to do to achieve this end. That's
> > way I'm happy to simply have the 'two main threads' and just managed
> > requests and notifications via queues. Obviously, in trying to do this,
> > a whole lot of things need to be taken into consideration, and
> > responsibilities and contracts need to be given to various components,
> > I'm trying to figure out what those should be, but if someone has
> > already done the work, I'd rather save myself some trouble.. :P
> >
> > Perhaps I should get myself a book on 'game programming'. Those guys
> > have been doing stuff like this for years right?
> >
> > The facilities in .NET alone at the moment are not of themselves
> > sophisticated enough to allow me to do everything that I want to do, so
> > I really need an application framework on top of .NET to help me.
> >
> > Obviously there are applications that work this way. Consider how VS.NET
> > works. If I have a class open in the code editor and change the class's
> > name, then the name change is reflected in the drop-down list on the
> > top, left and in the Class View. There is a slight delay in the UI being
> > updated however, and my keystrokes aren't delayed while the UI updates
> > itself (I think, I could be wrong about that), indicating that this
> > 'event' has been queued and dispatched. Basically I want to know about a
> > pattern for accomplishing functionality like that. Is it simply the case
> > that they are using WM_PAINT, and invalidating the control? If so, then
> > what is the UI thread going to do when it wants the current value for
> > the class name? Lock the business model of the Class so that it can read
> > out the name value, meaning that the code editor needs to acquire the
> > same lock when updating? I'm sure that because of all the parsing, etc
> > that would be required this software is *far* more sophisticated that
> > what I'm trying to achieve, but there are elements of a similar pattern
> > that must have been addressed here right? If I was to run a 'find and
> > replace' operation, then I wouldn't want my code to alter the code
> > editors text box, but rather the 'compile unit' or 'source file'
> > business object, then have the changes reflected in the text box (the
> > view). My system is not a text editor of course; it's basically a
> > glorified database browser.
> >
> > Should I just give in and leave all my code on the UI thread? The
> > reality is that in a 'typical' usage scenario the UI locks up for much
> > less than 500ms during an operation, but this still sucks right? In my
> > travels I've never seen any software adequately deal with all of these
> > problems.
> >
> > 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
> 
> ===================================
> 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
> 
> ---
> Incoming mail is certified Virus Free.
> Checked by AVG anti-virus system (http://www.grisoft.com).
> Version: 6.0.593 / Virus Database: 376 - Release Date: 20/02/2004
> 

---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.593 / Virus Database: 376 - Release Date: 20/02/2004
 

===================================
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