Here's one that should probably have the sub-heading "I'm sure I asked this
once before, but ...".
Two users are both looking at the same data, from a database. One user
changes the data and commits it. How does the other user get the updated
view without polling for changes? Is there some sort of callback mechanism
that can be set up on the dataset or connection?
TIA
Charles 30 3303
Hi Charles,
I am not sure about callback mechanisms, I think that Oracle had something
of that, but you can provide a Refresh button and a mechanism that when the
second user tries to change the data, he is notified that the data was
changed since it was retrieved from the database. This can be done using a
timestamp field which is retrieved along with the data. When you do the
update, you get the timestamp first to see if it is the same; if not,
someone else changed the data and you can offer the user a window to see the
changes.
--
Best regards,
Carlos J. Quintero
MZ-Tools: Productivity add-ins for Visual Studio
You can code, design and document much faster: http://www.mztools.com
"Charles Law" <bl***@nowhere.com> escribió en el mensaje
news:uY**************@TK2MSFTNGP05.phx.gbl... Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
Charles,
If you are using any kind of dataadapter/tableadapter and dataset/datatable
than it is quiet easy.
A dataset keeps track of the changed rows as long as you did not do
acceptchanges.
In the update process the code checks first row by row of those original
rows are changed in the database. (Created new, deleted or updated).
If that is the fact than you get a concurrency error.
Be aware that accepted rows are handled, so the recovery process is not
easy.
(Although you can set the connection with a begintransaction and a commit or
non commit of that).
Because of the fact that this situations in most situations is seldom, it is
called optimistic concurrency.
However you have to check it and creates the procedures.
Even if that is telling setting everything back to the first state and
telling the user to do his job again.
Very simple is it not?
Cor
"Charles Law" <bl***@nowhere.com> schreef in bericht
news:uY**************@TK2MSFTNGP05.phx.gbl... Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
Hi Carlos
Thanks for the reply. I was thinking more of an automatic way, so that the
second user is notified of the change when it happens, rather than if and
when he tries to make a change. This seems to me like something that would
be quite widely desired. I recollect now that I asked this before wrt web
applications, but I am now looking at a WinForms application, so perhaps
there is a way?
Charles
"Carlos J. Quintero [VB MVP]" <ca*****@NOSPAMsogecable.com> wrote in message
news:e1*************@TK2MSFTNGP02.phx.gbl... Hi Charles,
I am not sure about callback mechanisms, I think that Oracle had something of that, but you can provide a Refresh button and a mechanism that when the second user tries to change the data, he is notified that the data was changed since it was retrieved from the database. This can be done using a timestamp field which is retrieved along with the data. When you do the update, you get the timestamp first to see if it is the same; if not, someone else changed the data and you can offer the user a window to see the changes.
--
Best regards,
Carlos J. Quintero
MZ-Tools: Productivity add-ins for Visual Studio You can code, design and document much faster: http://www.mztools.com
"Charles Law" <bl***@nowhere.com> escribió en el mensaje news:uY**************@TK2MSFTNGP05.phx.gbl... Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
Hi Cor
Sorry if I am not catching on very quickly, but I don't quite see how your
scenario would work. A dataset keeps track of the changed rows as long as you did not do acceptchanges.
Isn't this the dataset of the user who has made the changes? What about the
dataset of the user who is just viewing the data? Does that get some
notification of the changes as well?
In the update process the code checks first row by row of those original rows are changed in the database. (Created new, deleted or updated).
This sounds like something that would happen when the second user tries to
make changes, in which case I agree that there would be some sort of error
because the data had already changed. But suppose the second user is just
looking at the data? Because datasets are disconnected in .NET it seems to
me that the second user might never see the changes unless he specifically
reloads the data.
Charles
"Cor Ligthert [MVP]" <no************@planet.nl> wrote in message
news:uu**************@TK2MSFTNGP02.phx.gbl... Charles,
If you are using any kind of dataadapter/tableadapter and dataset/datatable than it is quiet easy.
A dataset keeps track of the changed rows as long as you did not do acceptchanges.
In the update process the code checks first row by row of those original rows are changed in the database. (Created new, deleted or updated).
If that is the fact than you get a concurrency error. Be aware that accepted rows are handled, so the recovery process is not easy. (Although you can set the connection with a begintransaction and a commit or non commit of that).
Because of the fact that this situations in most situations is seldom, it is called optimistic concurrency. However you have to check it and creates the procedures. Even if that is telling setting everything back to the first state and telling the user to do his job again.
Very simple is it not?
Cor
"Charles Law" <bl***@nowhere.com> schreef in bericht news:uY**************@TK2MSFTNGP05.phx.gbl... Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
Charles,
The described process keeps only track for the updating user to prevent that
there will not wrong changed data because there where already changes in the
meantime.
What if the first was looking while the second was on the toilet and did the
updates after that while the other one was already not looking anymore.
Should there be a message that he/she was on the toilet but changed it?
This kind of pseudo accuratesse is in most situations already long time seen
as b*sh*t
However not there where there are automatic updates done for by instance by
a stock exchange.
Ken made this sample for this. Problem for me is that it will not work for
me without a 100% load so maybe can you try it as well. Ken has let this
tested by others and told that they had not that problem. http://www.vb-tips.com/default.aspx?...c-3503c15fd46e
Beside this it is of course advisable not to make processes that keeps to
long the changes data on the client. However if you are on a place where
there is really not any usable connection possible, than it can be that it
takes longer.
I hope this helps,
Cor
"Charles Law" <bl***@nowhere.com> schreef in bericht
news:u7**************@TK2MSFTNGP05.phx.gbl... Hi Cor
Sorry if I am not catching on very quickly, but I don't quite see how your scenario would work.
A dataset keeps track of the changed rows as long as you did not do acceptchanges.
Isn't this the dataset of the user who has made the changes? What about the dataset of the user who is just viewing the data? Does that get some notification of the changes as well?
In the update process the code checks first row by row of those original rows are changed in the database. (Created new, deleted or updated).
This sounds like something that would happen when the second user tries to make changes, in which case I agree that there would be some sort of error because the data had already changed. But suppose the second user is just looking at the data? Because datasets are disconnected in .NET it seems to me that the second user might never see the changes unless he specifically reloads the data.
Charles
"Cor Ligthert [MVP]" <no************@planet.nl> wrote in message news:uu**************@TK2MSFTNGP02.phx.gbl... Charles,
If you are using any kind of dataadapter/tableadapter and dataset/datatable than it is quiet easy.
A dataset keeps track of the changed rows as long as you did not do acceptchanges.
In the update process the code checks first row by row of those original rows are changed in the database. (Created new, deleted or updated).
If that is the fact than you get a concurrency error. Be aware that accepted rows are handled, so the recovery process is not easy. (Although you can set the connection with a begintransaction and a commit or non commit of that).
Because of the fact that this situations in most situations is seldom, it is called optimistic concurrency. However you have to check it and creates the procedures. Even if that is telling setting everything back to the first state and telling the user to do his job again.
Very simple is it not?
Cor
"Charles Law" <bl***@nowhere.com> schreef in bericht news:uY**************@TK2MSFTNGP05.phx.gbl... Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
AFAIK this is generally not widely wanted (after all if the other user would
have updated few minutes later, the user that is looking the data would have
not seen this change, so the first question is likely is this that critical
to have instant updates or is it enough to just see what is current when you
request for it comapred with the additional complexity/processing cost ? If
you have a special need, such as plane reservation or something similar you
may want to explain what you are trying to do...).
--
Patrice
"Charles Law" <bl***@nowhere.com> a écrit dans le message de news: u7**************@TK2MSFTNGP05.phx.gbl... Hi Cor
Sorry if I am not catching on very quickly, but I don't quite see how your scenario would work.
A dataset keeps track of the changed rows as long as you did not do acceptchanges.
Isn't this the dataset of the user who has made the changes? What about the dataset of the user who is just viewing the data? Does that get some notification of the changes as well?
In the update process the code checks first row by row of those original rows are changed in the database. (Created new, deleted or updated).
This sounds like something that would happen when the second user tries to make changes, in which case I agree that there would be some sort of error because the data had already changed. But suppose the second user is just looking at the data? Because datasets are disconnected in .NET it seems to me that the second user might never see the changes unless he specifically reloads the data.
Charles
"Cor Ligthert [MVP]" <no************@planet.nl> wrote in message news:uu**************@TK2MSFTNGP02.phx.gbl... Charles,
If you are using any kind of dataadapter/tableadapter and dataset/datatable than it is quiet easy.
A dataset keeps track of the changed rows as long as you did not do acceptchanges.
In the update process the code checks first row by row of those original rows are changed in the database. (Created new, deleted or updated).
If that is the fact than you get a concurrency error. Be aware that accepted rows are handled, so the recovery process is not easy. (Although you can set the connection with a begintransaction and a commit or non commit of that).
Because of the fact that this situations in most situations is seldom, it is called optimistic concurrency. However you have to check it and creates the procedures. Even if that is telling setting everything back to the first state and telling the user to do his job again.
Very simple is it not?
Cor
"Charles Law" <bl***@nowhere.com> schreef in bericht news:uY**************@TK2MSFTNGP05.phx.gbl... Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
Cor What if the first was looking while the second was on the toilet and did the updates after that while the other one was already not looking anymore. Should there be a message that he/she was on the toilet but changed it?
On return from the lavatory, the user's screen would be up-to-date, that's
all.
This kind of pseudo accuratesse is in most situations already long time seen as b*sh*t
By whom? It would seem that Microsoft do not see it that way, as they have
introduced the SqlDependency class in VS2005 to address just this situation.
Anyway, I think I have my answer: it is possible only in VS2005 with
SqlServer. Thanks.
Charles
"Cor Ligthert [MVP]" <no************@planet.nl> wrote in message
news:Of**************@TK2MSFTNGP04.phx.gbl... Charles,
The described process keeps only track for the updating user to prevent that there will not wrong changed data because there where already changes in the meantime.
What if the first was looking while the second was on the toilet and did the updates after that while the other one was already not looking anymore. Should there be a message that he/she was on the toilet but changed it?
This kind of pseudo accuratesse is in most situations already long time seen as b*sh*t
However not there where there are automatic updates done for by instance by a stock exchange.
Ken made this sample for this. Problem for me is that it will not work for me without a 100% load so maybe can you try it as well. Ken has let this tested by others and told that they had not that problem.
http://www.vb-tips.com/default.aspx?...c-3503c15fd46e
Beside this it is of course advisable not to make processes that keeps to long the changes data on the client. However if you are on a place where there is really not any usable connection possible, than it can be that it takes longer.
I hope this helps,
Cor
"Charles Law" <bl***@nowhere.com> schreef in bericht news:u7**************@TK2MSFTNGP05.phx.gbl... Hi Cor
Sorry if I am not catching on very quickly, but I don't quite see how your scenario would work.
A dataset keeps track of the changed rows as long as you did not do acceptchanges.
Isn't this the dataset of the user who has made the changes? What about the dataset of the user who is just viewing the data? Does that get some notification of the changes as well?
In the update process the code checks first row by row of those original rows are changed in the database. (Created new, deleted or updated).
This sounds like something that would happen when the second user tries to make changes, in which case I agree that there would be some sort of error because the data had already changed. But suppose the second user is just looking at the data? Because datasets are disconnected in .NET it seems to me that the second user might never see the changes unless he specifically reloads the data.
Charles
"Cor Ligthert [MVP]" <no************@planet.nl> wrote in message news:uu**************@TK2MSFTNGP02.phx.gbl... Charles,
If you are using any kind of dataadapter/tableadapter and dataset/datatable than it is quiet easy.
A dataset keeps track of the changed rows as long as you did not do acceptchanges.
In the update process the code checks first row by row of those original rows are changed in the database. (Created new, deleted or updated).
If that is the fact than you get a concurrency error. Be aware that accepted rows are handled, so the recovery process is not easy. (Although you can set the connection with a begintransaction and a commit or non commit of that).
Because of the fact that this situations in most situations is seldom, it is called optimistic concurrency. However you have to check it and creates the procedures. Even if that is telling setting everything back to the first state and telling the user to do his job again.
Very simple is it not?
Cor
"Charles Law" <bl***@nowhere.com> schreef in bericht news:uY**************@TK2MSFTNGP05.phx.gbl... Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
Charles, This kind of pseudo accuratesse is in most situations already long time seen as b*sh*t
By whom? It would seem that Microsoft do not see it that way, as they have introduced the SqlDependency class in VS2005 to address just this situation.
I showed you that there are situations where that can be the fact.
However mostly not if it is about humans who are updating.
The same as I did with other words is writen by Patrice by the way.
Cor
Hi Patrice
Thanks for the reply. ... such as plane reservation or something similar ...
That is a good example. Also, a bank call centre. The advisor is referring
to information on-screen whilst discussing details with a caller.
Transactions occur asynchronously, so the account balance could change
whilst the call is in progress. Unless the advisor repeatedly presses an
update button, they would not see the changes.
The stock market prices change by the second, and it is important that
traders have up-to-the-second prices on their screens. Polling is very
inefficient. The observer pattern was made for this scenario but I am
hearing that it can't be implemented on a database. I still think that this
_is_ widely wanted, but that we are largely being told that it can't be
done.
Charles
"Patrice" <sc****@chez.com> wrote in message
news:%2****************@TK2MSFTNGP05.phx.gbl... AFAIK this is generally not widely wanted (after all if the other user would have updated few minutes later, the user that is looking the data would have not seen this change, so the first question is likely is this that critical to have instant updates or is it enough to just see what is current when you request for it comapred with the additional complexity/processing cost ? If you have a special need, such as plane reservation or something similar you may want to explain what you are trying to do...).
-- Patrice
"Charles Law" <bl***@nowhere.com> a écrit dans le message de news: u7**************@TK2MSFTNGP05.phx.gbl... Hi Cor
Sorry if I am not catching on very quickly, but I don't quite see how your scenario would work.
A dataset keeps track of the changed rows as long as you did not do acceptchanges.
Isn't this the dataset of the user who has made the changes? What about the dataset of the user who is just viewing the data? Does that get some notification of the changes as well?
In the update process the code checks first row by row of those original rows are changed in the database. (Created new, deleted or updated).
This sounds like something that would happen when the second user tries to make changes, in which case I agree that there would be some sort of error because the data had already changed. But suppose the second user is just looking at the data? Because datasets are disconnected in .NET it seems to me that the second user might never see the changes unless he specifically reloads the data.
Charles
"Cor Ligthert [MVP]" <no************@planet.nl> wrote in message news:uu**************@TK2MSFTNGP02.phx.gbl... Charles,
If you are using any kind of dataadapter/tableadapter and dataset/datatable than it is quiet easy.
A dataset keeps track of the changed rows as long as you did not do acceptchanges.
In the update process the code checks first row by row of those original rows are changed in the database. (Created new, deleted or updated).
If that is the fact than you get a concurrency error. Be aware that accepted rows are handled, so the recovery process is not easy. (Although you can set the connection with a begintransaction and a commit or non commit of that).
Because of the fact that this situations in most situations is seldom, it is called optimistic concurrency. However you have to check it and creates the procedures. Even if that is telling setting everything back to the first state and telling the user to do his job again.
Very simple is it not?
Cor
"Charles Law" <bl***@nowhere.com> schreef in bericht news:uY**************@TK2MSFTNGP05.phx.gbl... Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
I am currently implementing a pattern that allows this to happen. It is
actually a non-trivial problem. My pattern uses a worker thread for
performing operations, I have my own data cache, ie. I don't use data sets.
The thread checks the cache in idle time to see if anything has changed and
fires off Update, Delete, Insert and Move (it's a tree structure so I need
this one) methods to it's listeners. UI components (user controls) register
with the data cache as listeners for these kind of events and implement an
IDataUpdateThreadNotification interface. In actuality, there are over 60
different kinds of event. Note that the worker thread does not directly
alter the cache, it only reads it, fetches any relevant data and then
invokes a method on the cache object to resolve any changes that were
detected.
For example, consider I have a set of records in an array, stored in my
cache. The process would look like this:
(1) Thread is idling, so it decides to do a "coherency check"
(2) Thread creates a data connection and fetches the records
(3) Thread Invokes a method on the cache called "RecordsFetched"
....
(4) Cache compares all of the time stamps in the fetched records with the
current records and:
Any timestamps that are different, fires an Updated event to it's
listeners
Any records that exist in the fetched set but not in the cache, fires an
Inserted event to it's listeners
Any records that exist in the cache by not in the fetched set, fires a
Deleted event to it's listeners
Anyway, this is the basis I am working from with all of my (somewhat
complex) data structures. Perhaps it's easier with a single data set. I
would definatley avoid any server event notification systems - it's too easy
for your client to miss a message and thereby mess up your state.
"Charles Law" <bl***@nowhere.com> wrote in message
news:uY**************@TK2MSFTNGP05.phx.gbl... Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
Charles The stock market prices change by the second, and it is important that traders have up-to-the-second prices on their screens. Polling is very inefficient. The observer pattern was made for this scenario but I am hearing that it can't be implemented on a database. I still think that this _is_ widely wanted, but that we are largely being told that it can't be done.
I gave an half our ago a message that you have read wherin I wrote that
this are the situations where it is needed complete with a sample from Ken
about that. (Using the notify), I have however the idea that you did not
even look at it.
Therefore why are you writing this while I wrote that already, secondly as
forever did you not give that information in your first message. Not every
application is a broker application you know?
:-)
Cor
Have I upset you in some way Cor? I gave an half our ago a message that you have read wherin I wrote that this are the situations where it is needed complete with a sample from Ken about that. (Using the notify), I have however the idea that you did not even look at it.
In fact I did, and bookmarked it. That is how I knew that the SqlDependency
class had been introduced in VS2005.
Therefore why are you writing this while I wrote that already, secondly as forever did you not give that information in your first message. Not every application is a broker application you know?
Indeed, but why would I be asking about a notify feature if I did not want
it for a good reason?
:-)
Charles
"Cor Ligthert [MVP]" <no************@planet.nl> wrote in message
news:e6**************@TK2MSFTNGP05.phx.gbl... Charles The stock market prices change by the second, and it is important that traders have up-to-the-second prices on their screens. Polling is very inefficient. The observer pattern was made for this scenario but I am hearing that it can't be implemented on a database. I still think that this _is_ widely wanted, but that we are largely being told that it can't be done.
I gave an half our ago a message that you have read wherin I wrote that this are the situations where it is needed complete with a sample from Ken about that. (Using the notify), I have however the idea that you did not even look at it.
Therefore why are you writing this while I wrote that already, secondly as forever did you not give that information in your first message. Not every application is a broker application you know?
:-)
Cor
Hi My pattern uses a worker thread for performing operations, I have my own data cache, ie. I don't use data sets. The thread checks the cache in idle time to see if anything has changed and fires off Update, Delete, Insert and Move (it's a tree structure so I need this one) methods to it's listeners. UI components (user controls) register with the data cache as listeners for these kind of events and implement an IDataUpdateThreadNotification interface.
I might have a go at this; I take your point about the danger of missing a
server message. Although it shouldn't happen, I have no doubt that it could.
Have you determined a suitable frequency for checking in your worker thread?
Where do you create the data caches, on the UI thread or the worker thread?
Charles
"RMT" <no****@nospam.com> wrote in message
news:e6*******************@news.demon.co.uk... I am currently implementing a pattern that allows this to happen. It is actually a non-trivial problem. My pattern uses a worker thread for performing operations, I have my own data cache, ie. I don't use data sets. The thread checks the cache in idle time to see if anything has changed and fires off Update, Delete, Insert and Move (it's a tree structure so I need this one) methods to it's listeners. UI components (user controls) register with the data cache as listeners for these kind of events and implement an IDataUpdateThreadNotification interface. In actuality, there are over 60 different kinds of event. Note that the worker thread does not directly alter the cache, it only reads it, fetches any relevant data and then invokes a method on the cache object to resolve any changes that were detected.
For example, consider I have a set of records in an array, stored in my cache. The process would look like this:
(1) Thread is idling, so it decides to do a "coherency check" (2) Thread creates a data connection and fetches the records (3) Thread Invokes a method on the cache called "RecordsFetched" ... (4) Cache compares all of the time stamps in the fetched records with the current records and:
Any timestamps that are different, fires an Updated event to it's listeners Any records that exist in the fetched set but not in the cache, fires an Inserted event to it's listeners Any records that exist in the cache by not in the fetched set, fires a Deleted event to it's listeners
Anyway, this is the basis I am working from with all of my (somewhat complex) data structures. Perhaps it's easier with a single data set. I would definatley avoid any server event notification systems - it's too easy for your client to miss a message and thereby mess up your state.
"Charles Law" <bl***@nowhere.com> wrote in message news:uY**************@TK2MSFTNGP05.phx.gbl... Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
The data cache is really the central controller of the whole thing, created
on the UI thread. It basically mediates between the UI components and the
worker thread and the worker thread does all the talking to the database.
The thread maintains queues of operations to perform. The data cache adds a
request to the queue when something needs to be done, for example:
User clicks ADD RECORD button on a toolbar
Code behind the toolbar click tells the cache to ADD RECORD
The cache formats a request and queues it at the thread,
theThread.AddRequest (theRequest, CRITICAL)
....then forgets about it.
I have 3 queues: CRITICAL, UI and BORED. Critical is for performing
operations the user requests, UI is for things like fetching thumbnails (in
my application this is a neccessary evil) and BORED is for coherency
checking and other stuff like that.
On each iteration of the worker thread loop ( while not m_bFinished () ), it
takes the single highest priority item from the list of queues and executes
it. If there is nothing in any of the lists, it idles for 100ms (so it
doesn't take up all CPU) - after idling it will choose something to check
coherency for (in my case the Tree Structure, Thumbnails, etc.) and creates
a request, adding it to the BORED queue. Then:
Thread de-queues the single highest priority request
Executes it
Invokes the result back to the cache
The cache resolves changes and fires events to it's listeners.
In terms of frequency, I leave this up to the user. You have to trade
coherency against network traffic and performance - my application is
designed to be able to connect to a webserver via. SOAP or ASP.NET, so it's
important I can throttle the coherency check down if I need to.
Note that even with high coherency, the user can still execute an action and
have it fail - ie. it's still possible to attempt to modify a record another
user has deleted, if you do it before the coherency check works out that the
record was deleted. To handle this case, you simply tell the user with an
error message, ie. "The record could not be modified because it no longer
exists".
It's really a simple pattern but implementation details can be more tricky.
If you need any help, post up :).
"Charles Law" <bl***@nowhere.com> wrote in message
news:ed**************@TK2MSFTNGP05.phx.gbl... Hi
My pattern uses a worker thread for performing operations, I have my own data cache, ie. I don't use data sets. The thread checks the cache in idle time to see if anything has changed and fires off Update, Delete, Insert and Move (it's a tree structure so I need this one) methods to it's listeners. UI components (user controls) register with the data cache as listeners for these kind of events and implement an IDataUpdateThreadNotification interface.
I might have a go at this; I take your point about the danger of missing a server message. Although it shouldn't happen, I have no doubt that it could.
Have you determined a suitable frequency for checking in your worker thread? Where do you create the data caches, on the UI thread or the worker thread?
Charles
"RMT" <no****@nospam.com> wrote in message news:e6*******************@news.demon.co.uk... I am currently implementing a pattern that allows this to happen. It is actually a non-trivial problem. My pattern uses a worker thread for performing operations, I have my own data cache, ie. I don't use data sets. The thread checks the cache in idle time to see if anything has changed and fires off Update, Delete, Insert and Move (it's a tree structure so I need this one) methods to it's listeners. UI components (user controls) register with the data cache as listeners for these kind of events and implement an IDataUpdateThreadNotification interface. In actuality, there are over 60 different kinds of event. Note that the worker thread does not directly alter the cache, it only reads it, fetches any relevant data and then invokes a method on the cache object to resolve any changes that were detected.
For example, consider I have a set of records in an array, stored in my cache. The process would look like this:
(1) Thread is idling, so it decides to do a "coherency check" (2) Thread creates a data connection and fetches the records (3) Thread Invokes a method on the cache called "RecordsFetched" ... (4) Cache compares all of the time stamps in the fetched records with the current records and:
Any timestamps that are different, fires an Updated event to it's listeners Any records that exist in the fetched set but not in the cache, fires an Inserted event to it's listeners Any records that exist in the cache by not in the fetched set, fires a Deleted event to it's listeners
Anyway, this is the basis I am working from with all of my (somewhat complex) data structures. Perhaps it's easier with a single data set. I would definatley avoid any server event notification systems - it's too easy for your client to miss a message and thereby mess up your state.
"Charles Law" <bl***@nowhere.com> wrote in message news:uY**************@TK2MSFTNGP05.phx.gbl... Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
I'm not really convinced by the bank sample. It could be blocked when the
transaction is actually processed IMO there is no need to see the amount
refreshed in real time. I'm not even sure the idea is not that it will be
blocked soon enough by the following transaction if not by the current
one....
The stock market price is much more convincing (but this is a niche not
something widely wanted). Several options would be :
- polling
- sql dependency
- callback coming from the server (using remoting, web services, broadcast
or multicast message etc)
etc...
What is your specific scenario ?
--
Patrice
"Charles Law" <bl***@nowhere.com> a écrit dans le message de news: OS**************@TK2MSFTNGP03.phx.gbl... Hi Patrice
Thanks for the reply.
... such as plane reservation or something similar ...
That is a good example. Also, a bank call centre. The advisor is referring to information on-screen whilst discussing details with a caller. Transactions occur asynchronously, so the account balance could change whilst the call is in progress. Unless the advisor repeatedly presses an update button, they would not see the changes.
The stock market prices change by the second, and it is important that traders have up-to-the-second prices on their screens. Polling is very inefficient. The observer pattern was made for this scenario but I am hearing that it can't be implemented on a database. I still think that this _is_ widely wanted, but that we are largely being told that it can't be done.
Charles
"Patrice" <sc****@chez.com> wrote in message news:%2****************@TK2MSFTNGP05.phx.gbl... AFAIK this is generally not widely wanted (after all if the other user would have updated few minutes later, the user that is looking the data would have not seen this change, so the first question is likely is this that critical to have instant updates or is it enough to just see what is current when you request for it comapred with the additional complexity/processing cost ? If you have a special need, such as plane reservation or something similar you may want to explain what you are trying to do...).
-- Patrice
"Charles Law" <bl***@nowhere.com> a écrit dans le message de news: u7**************@TK2MSFTNGP05.phx.gbl... Hi Cor
Sorry if I am not catching on very quickly, but I don't quite see how your scenario would work.
A dataset keeps track of the changed rows as long as you did not do acceptchanges.
Isn't this the dataset of the user who has made the changes? What about the dataset of the user who is just viewing the data? Does that get some notification of the changes as well?
In the update process the code checks first row by row of those original rows are changed in the database. (Created new, deleted or updated).
This sounds like something that would happen when the second user tries to make changes, in which case I agree that there would be some sort of error because the data had already changed. But suppose the second user is just looking at the data? Because datasets are disconnected in .NET it seems to me that the second user might never see the changes unless he specifically reloads the data.
Charles
"Cor Ligthert [MVP]" <no************@planet.nl> wrote in message news:uu**************@TK2MSFTNGP02.phx.gbl... Charles,
If you are using any kind of dataadapter/tableadapter and dataset/datatable than it is quiet easy.
A dataset keeps track of the changed rows as long as you did not do acceptchanges.
In the update process the code checks first row by row of those original rows are changed in the database. (Created new, deleted or updated).
If that is the fact than you get a concurrency error. Be aware that accepted rows are handled, so the recovery process is not easy. (Although you can set the connection with a begintransaction and a commit or non commit of that).
Because of the fact that this situations in most situations is seldom, it is called optimistic concurrency. However you have to check it and creates the procedures. Even if that is telling setting everything back to the first state and telling the user to do his job again.
Very simple is it not?
Cor
"Charles Law" <bl***@nowhere.com> schreef in bericht news:uY**************@TK2MSFTNGP05.phx.gbl... > Here's one that should probably have the sub-heading "I'm sure I asked > this once before, but ...". > > Two users are both looking at the same data, from a database. One user > changes the data and commits it. How does the other user get the > updated view without polling for changes? Is there some sort of > callback mechanism that can be set up on the dataset or connection? > > TIA > > Charles > >
I see what you mean about non-trivial ;-)
I will read and digest. It is the kind of thing that could fit with my
scenario.
Thanks.
Charles
"RMT" <no****@nospam.com> wrote in message
news:e6*******************@news.demon.co.uk... The data cache is really the central controller of the whole thing, created on the UI thread. It basically mediates between the UI components and the worker thread and the worker thread does all the talking to the database. The thread maintains queues of operations to perform. The data cache adds a request to the queue when something needs to be done, for example:
User clicks ADD RECORD button on a toolbar Code behind the toolbar click tells the cache to ADD RECORD The cache formats a request and queues it at the thread, theThread.AddRequest (theRequest, CRITICAL) ...then forgets about it.
I have 3 queues: CRITICAL, UI and BORED. Critical is for performing operations the user requests, UI is for things like fetching thumbnails (in my application this is a neccessary evil) and BORED is for coherency checking and other stuff like that.
On each iteration of the worker thread loop ( while not m_bFinished () ), it takes the single highest priority item from the list of queues and executes it. If there is nothing in any of the lists, it idles for 100ms (so it doesn't take up all CPU) - after idling it will choose something to check coherency for (in my case the Tree Structure, Thumbnails, etc.) and creates a request, adding it to the BORED queue. Then:
Thread de-queues the single highest priority request Executes it Invokes the result back to the cache The cache resolves changes and fires events to it's listeners. In terms of frequency, I leave this up to the user. You have to trade coherency against network traffic and performance - my application is designed to be able to connect to a webserver via. SOAP or ASP.NET, so it's important I can throttle the coherency check down if I need to.
Note that even with high coherency, the user can still execute an action and have it fail - ie. it's still possible to attempt to modify a record another user has deleted, if you do it before the coherency check works out that the record was deleted. To handle this case, you simply tell the user with an error message, ie. "The record could not be modified because it no longer exists".
It's really a simple pattern but implementation details can be more tricky. If you need any help, post up :). "Charles Law" <bl***@nowhere.com> wrote in message news:ed**************@TK2MSFTNGP05.phx.gbl... Hi
My pattern uses a worker thread for performing operations, I have my own data cache, ie. I don't use data sets. The thread checks the cache in idle time to see if anything has changed and fires off Update, Delete, Insert and Move (it's a tree structure so I need this one) methods to it's listeners. UI components (user controls) register with the data cache as listeners for these kind of events and implement an IDataUpdateThreadNotification interface.
I might have a go at this; I take your point about the danger of missing a server message. Although it shouldn't happen, I have no doubt that it could.
Have you determined a suitable frequency for checking in your worker thread? Where do you create the data caches, on the UI thread or the worker thread?
Charles
"RMT" <no****@nospam.com> wrote in message news:e6*******************@news.demon.co.uk... I am currently implementing a pattern that allows this to happen. It is actually a non-trivial problem. My pattern uses a worker thread for performing operations, I have my own data cache, ie. I don't use data sets. The thread checks the cache in idle time to see if anything has changed and fires off Update, Delete, Insert and Move (it's a tree structure so I need this one) methods to it's listeners. UI components (user controls) register with the data cache as listeners for these kind of events and implement an IDataUpdateThreadNotification interface. In actuality, there are over 60 different kinds of event. Note that the worker thread does not directly alter the cache, it only reads it, fetches any relevant data and then invokes a method on the cache object to resolve any changes that were detected.
For example, consider I have a set of records in an array, stored in my cache. The process would look like this:
(1) Thread is idling, so it decides to do a "coherency check" (2) Thread creates a data connection and fetches the records (3) Thread Invokes a method on the cache called "RecordsFetched" ... (4) Cache compares all of the time stamps in the fetched records with the current records and:
Any timestamps that are different, fires an Updated event to it's listeners Any records that exist in the fetched set but not in the cache, fires an Inserted event to it's listeners Any records that exist in the cache by not in the fetched set, fires a Deleted event to it's listeners
Anyway, this is the basis I am working from with all of my (somewhat complex) data structures. Perhaps it's easier with a single data set. I would definatley avoid any server event notification systems - it's too easy for your client to miss a message and thereby mess up your state.
"Charles Law" <bl***@nowhere.com> wrote in message news:uY**************@TK2MSFTNGP05.phx.gbl... Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
With SQL 2005, yes. With SQL 2000, it can be set up, but it will still poll
in the background. I am not sure about Oracle, but there is probably
something there. If the client is fully connected, you can build a
mechanism, as well, but you are on your own keeping track of who has what
data, which may cost more than the benefit of avoiding concurrency issues
rather than just reducing them.
--
Gregory A. Beamer
*************************************************
Think Outside the Box!
*************************************************
"Charles Law" <bl***@nowhere.com> wrote in message
news:uY**************@TK2MSFTNGP05.phx.gbl... Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
> What is your specific scenario ?
An accountancy tool, that will start small, but will scale to multiple
users. Some of the screens might be left open for some minutes, whilst the
data backing them will be available to other users. Any or all of the users
could potentially modify the data, and the others must be able to see the
changes when they happen.
Charles
"Patrice" <sc****@chez.com> wrote in message
news:Oo**************@TK2MSFTNGP04.phx.gbl... I'm not really convinced by the bank sample. It could be blocked when the transaction is actually processed IMO there is no need to see the amount refreshed in real time. I'm not even sure the idea is not that it will be blocked soon enough by the following transaction if not by the current one....
The stock market price is much more convincing (but this is a niche not something widely wanted). Several options would be : - polling - sql dependency - callback coming from the server (using remoting, web services, broadcast or multicast message etc) etc...
What is your specific scenario ?
-- Patrice
"Charles Law" <bl***@nowhere.com> a écrit dans le message de news: OS**************@TK2MSFTNGP03.phx.gbl... Hi Patrice
Thanks for the reply.
... such as plane reservation or something similar ...
That is a good example. Also, a bank call centre. The advisor is referring to information on-screen whilst discussing details with a caller. Transactions occur asynchronously, so the account balance could change whilst the call is in progress. Unless the advisor repeatedly presses an update button, they would not see the changes.
The stock market prices change by the second, and it is important that traders have up-to-the-second prices on their screens. Polling is very inefficient. The observer pattern was made for this scenario but I am hearing that it can't be implemented on a database. I still think that this _is_ widely wanted, but that we are largely being told that it can't be done.
Charles
"Patrice" <sc****@chez.com> wrote in message news:%2****************@TK2MSFTNGP05.phx.gbl... AFAIK this is generally not widely wanted (after all if the other user would have updated few minutes later, the user that is looking the data would have not seen this change, so the first question is likely is this that critical to have instant updates or is it enough to just see what is current when you request for it comapred with the additional complexity/processing cost ? If you have a special need, such as plane reservation or something similar you may want to explain what you are trying to do...).
-- Patrice
"Charles Law" <bl***@nowhere.com> a écrit dans le message de news: u7**************@TK2MSFTNGP05.phx.gbl... Hi Cor
Sorry if I am not catching on very quickly, but I don't quite see how your scenario would work.
> A dataset keeps track of the changed rows as long as you did not do > acceptchanges.
Isn't this the dataset of the user who has made the changes? What about the dataset of the user who is just viewing the data? Does that get some notification of the changes as well?
> In the update process the code checks first row by row of those > original rows are changed in the database. (Created new, deleted or > updated).
This sounds like something that would happen when the second user tries to make changes, in which case I agree that there would be some sort of error because the data had already changed. But suppose the second user is just looking at the data? Because datasets are disconnected in .NET it seems to me that the second user might never see the changes unless he specifically reloads the data.
Charles
"Cor Ligthert [MVP]" <no************@planet.nl> wrote in message news:uu**************@TK2MSFTNGP02.phx.gbl... > Charles, > > If you are using any kind of dataadapter/tableadapter and > dataset/datatable than it is quiet easy. > > A dataset keeps track of the changed rows as long as you did not do > acceptchanges. > > In the update process the code checks first row by row of those > original rows are changed in the database. (Created new, deleted or > updated). > > If that is the fact than you get a concurrency error. > Be aware that accepted rows are handled, so the recovery process is > not easy. > (Although you can set the connection with a begintransaction and a > commit or non commit of that). > > Because of the fact that this situations in most situations is seldom, > it is called optimistic concurrency. > However you have to check it and creates the procedures. > Even if that is telling setting everything back to the first state and > telling the user to do his job again. > > Very simple is it not? > > Cor > > "Charles Law" <bl***@nowhere.com> schreef in bericht > news:uY**************@TK2MSFTNGP05.phx.gbl... >> Here's one that should probably have the sub-heading "I'm sure I >> asked this once before, but ...". >> >> Two users are both looking at the same data, from a database. One >> user changes the data and commits it. How does the other user get the >> updated view without polling for changes? Is there some sort of >> callback mechanism that can be set up on the dataset or connection? >> >> TIA >> >> Charles >> >> > >
Hi,
Then you need:
- A polling mechanism every n seconds
- Some specific notification system for updates provided by your database,
if available.
AFAIK, the standard database objects of the APIs (ADO, ODBC, etc.) don't
provide any of this.
Another approach is to prevent data modifications while a user is viewing it
(row-level locking). This is done in Oracle with a SELECT .. FOR UPDATE
statement, for example. Depending on your app, this kind of lock while
viewing data can be suitable or overkill.
All other approaches detect the conflict after the fact, when the second
user tries to modify data that was not the one that he got initially, as I
explained using a timestamp (or using dynamic recordsets, datasets, etc.
which I suppose that do the same internally)
--
Best regards,
Carlos J. Quintero
MZ-Tools: Productivity add-ins for Visual Studio
You can code, design and document much faster: http://www.mztools.com
"Charles Law" <bl***@nowhere.com> escribió en el mensaje
news:%2****************@TK2MSFTNGP03.phx.gbl... Hi Carlos
Thanks for the reply. I was thinking more of an automatic way, so that the second user is notified of the change when it happens, rather than if and when he tries to make a change. This seems to me like something that would be quite widely desired. I recollect now that I asked this before wrt web applications, but I am now looking at a WinForms application, so perhaps there is a way?
Charles
Hi Carlos - A polling mechanism every n seconds
Although not my preferred choice originally, RMT has given me some food for
thought, so I can see me going down this route.
Thanks.
Charles
"Carlos J. Quintero [VB MVP]" <ca*****@NOSPAMsogecable.com> wrote in message
news:eq**************@TK2MSFTNGP04.phx.gbl... Hi,
Then you need:
- A polling mechanism every n seconds - Some specific notification system for updates provided by your database, if available.
AFAIK, the standard database objects of the APIs (ADO, ODBC, etc.) don't provide any of this.
Another approach is to prevent data modifications while a user is viewing it (row-level locking). This is done in Oracle with a SELECT .. FOR UPDATE statement, for example. Depending on your app, this kind of lock while viewing data can be suitable or overkill.
All other approaches detect the conflict after the fact, when the second user tries to modify data that was not the one that he got initially, as I explained using a timestamp (or using dynamic recordsets, datasets, etc. which I suppose that do the same internally) --
Best regards,
Carlos J. Quintero
MZ-Tools: Productivity add-ins for Visual Studio You can code, design and document much faster: http://www.mztools.com "Charles Law" <bl***@nowhere.com> escribió en el mensaje news:%2****************@TK2MSFTNGP03.phx.gbl... Hi Carlos
Thanks for the reply. I was thinking more of an automatic way, so that the second user is notified of the change when it happens, rather than if and when he tries to make a change. This seems to me like something that would be quite widely desired. I recollect now that I asked this before wrt web applications, but I am now looking at a WinForms application, so perhaps there is a way?
Charles
Well in my case, the implementation details are more complicated, yes - as
an example of implementation detail, which I think is specific to my kind of
application:
(1) Prioritise Thread Requests
(2) Ensure low priority requests don't block high priority ones
(3) Error handling in the thread
(4) Listeners registering only for the events they are interested in
(5) Different types of coherency check
(6) Ensure coherency check "chunks", rather than checks an entire structure
at once
(7) Tree structure - reason about a tree from the flat structure a RDBMS
returns
(8) Enforce pattern on UI components
But in the simplest case - wanting to keep a record set coherent, it isn't
so hard.
Some general principles:
(1) A cache object to store the state you want to persist
(2) A worker thread
(3) A way for the thread to talk to the cache (Invoking methods on an
interface), so
(4) An interface for the Cache object to implement so it can receive
messages from (3)
(5) An abstract class from which your UI components can derive
(6) A list of listeners in your Cache Object, i.e. list of references to (5)
(7) A base "Operation" class, which encapsulates any operation you perform
on the data.
(8) Derived classes to actually perform the operations (ie. add, delete,
update, etc.)
(9) Methods on your data cache that construct objects from (8) and queue
them at (2)
Finally, data will flow around the system:
Either:
User interacts with UI component
UI component executes a Cache method (ie. "InsertRecord ( aaaabbbb )" )
Cache Object constructs request and adds to worker thread queue
or
Worker thread is in idle time, constructs a coherency check and adds it to
it's own queue
and then.....
Worker Thread iterates it's queue, executing each request in turn
Request Invokes a method on Cache interface (marshall across threads)
Cache resolves changes
Cache fires event on all of it's listeners
UI component changes it's state according to the event fired.
"Charles Law" <bl***@nowhere.com> escribió en el mensaje
news:Oa**************@TK2MSFTNGP02.phx.gbl... I see what you mean about non-trivial ;-)
I will read and digest. It is the kind of thing that could fit with my scenario.
Thanks.
Charles
"RMT" <no****@nospam.com> wrote in message news:e6*******************@news.demon.co.uk... The data cache is really the central controller of the whole thing, created on the UI thread. It basically mediates between the UI components and the worker thread and the worker thread does all the talking to the database. The thread maintains queues of operations to perform. The data cache adds a request to the queue when something needs to be done, for example:
User clicks ADD RECORD button on a toolbar Code behind the toolbar click tells the cache to ADD RECORD The cache formats a request and queues it at the thread, theThread.AddRequest (theRequest, CRITICAL) ...then forgets about it.
I have 3 queues: CRITICAL, UI and BORED. Critical is for performing operations the user requests, UI is for things like fetching thumbnails (in my application this is a neccessary evil) and BORED is for coherency checking and other stuff like that.
On each iteration of the worker thread loop ( while not m_bFinished () ), it takes the single highest priority item from the list of queues and executes it. If there is nothing in any of the lists, it idles for 100ms (so it doesn't take up all CPU) - after idling it will choose something to check coherency for (in my case the Tree Structure, Thumbnails, etc.) and creates a request, adding it to the BORED queue. Then:
Thread de-queues the single highest priority request Executes it Invokes the result back to the cache The cache resolves changes and fires events to it's listeners. In terms of frequency, I leave this up to the user. You have to trade coherency against network traffic and performance - my application is designed to be able to connect to a webserver via. SOAP or ASP.NET, so it's important I can throttle the coherency check down if I need to.
Note that even with high coherency, the user can still execute an action and have it fail - ie. it's still possible to attempt to modify a record another user has deleted, if you do it before the coherency check works out that the record was deleted. To handle this case, you simply tell the user with an error message, ie. "The record could not be modified because it no longer exists".
It's really a simple pattern but implementation details can be more tricky. If you need any help, post up :). "Charles Law" <bl***@nowhere.com> wrote in message news:ed**************@TK2MSFTNGP05.phx.gbl... Hi
My pattern uses a worker thread for performing operations, I have my own data cache, ie. I don't use data sets. The thread checks the cache in idle time to see if anything has changed and fires off Update, Delete, Insert and Move (it's a tree structure so I need this one) methods to it's listeners. UI components (user controls) register with the data cache as listeners for these kind of events and implement an IDataUpdateThreadNotification interface.
I might have a go at this; I take your point about the danger of missing a server message. Although it shouldn't happen, I have no doubt that it could.
Have you determined a suitable frequency for checking in your worker thread? Where do you create the data caches, on the UI thread or the worker thread?
Charles
"RMT" <no****@nospam.com> wrote in message news:e6*******************@news.demon.co.uk...
I am currently implementing a pattern that allows this to happen. It is actually a non-trivial problem. My pattern uses a worker thread for performing operations, I have my own data cache, ie. I don't use data sets. The thread checks the cache in idle time to see if anything has changed and fires off Update, Delete, Insert and Move (it's a tree structure so I need this one) methods to it's listeners. UI components (user controls) register with the data cache as listeners for these kind of events and implement an IDataUpdateThreadNotification interface. In actuality, there are over 60 different kinds of event. Note that the worker thread does not directly alter the cache, it only reads it, fetches any relevant data and then invokes a method on the cache object to resolve any changes that were detected.
For example, consider I have a set of records in an array, stored in my cache. The process would look like this:
(1) Thread is idling, so it decides to do a "coherency check" (2) Thread creates a data connection and fetches the records (3) Thread Invokes a method on the cache called "RecordsFetched" ... (4) Cache compares all of the time stamps in the fetched records with the current records and:
Any timestamps that are different, fires an Updated event to it's listeners Any records that exist in the fetched set but not in the cache, fires an Inserted event to it's listeners Any records that exist in the cache by not in the fetched set, fires a Deleted event to it's listeners
Anyway, this is the basis I am working from with all of my (somewhat complex) data structures. Perhaps it's easier with a single data set. I would definatley avoid any server event notification systems - it's too easy for your client to miss a message and thereby mess up your state.
"Charles Law" <bl***@nowhere.com> wrote in message news:uY**************@TK2MSFTNGP05.phx.gbl... > Here's one that should probably have the sub-heading "I'm sure I asked > this once before, but ...". > > Two users are both looking at the same data, from a database. One user > changes the data and commits it. How does the other user get the > updated view without polling for changes? Is there some sort of > callback mechanism that can be set up on the dataset or connection? > > TIA > > Charles > >
You have obviously taken a comprehensive approach to developing this
pattern. Have you found that it is efficient in terms of cpu time? How many
rows do you return on an average round-trip? Do you have any metric for the
reaction time of the UI to changes in the data?
Charles
"RMT" <no****@nospam.com> wrote in message
news:e6*******************@news.demon.co.uk... Well in my case, the implementation details are more complicated, yes - as an example of implementation detail, which I think is specific to my kind of application:
(1) Prioritise Thread Requests (2) Ensure low priority requests don't block high priority ones (3) Error handling in the thread (4) Listeners registering only for the events they are interested in (5) Different types of coherency check (6) Ensure coherency check "chunks", rather than checks an entire structure at once (7) Tree structure - reason about a tree from the flat structure a RDBMS returns (8) Enforce pattern on UI components
But in the simplest case - wanting to keep a record set coherent, it isn't so hard.
Some general principles:
(1) A cache object to store the state you want to persist (2) A worker thread (3) A way for the thread to talk to the cache (Invoking methods on an interface), so (4) An interface for the Cache object to implement so it can receive messages from (3) (5) An abstract class from which your UI components can derive (6) A list of listeners in your Cache Object, i.e. list of references to (5) (7) A base "Operation" class, which encapsulates any operation you perform on the data. (8) Derived classes to actually perform the operations (ie. add, delete, update, etc.) (9) Methods on your data cache that construct objects from (8) and queue them at (2)
Finally, data will flow around the system:
Either:
User interacts with UI component UI component executes a Cache method (ie. "InsertRecord ( aaaabbbb )" ) Cache Object constructs request and adds to worker thread queue
or
Worker thread is in idle time, constructs a coherency check and adds it to it's own queue
and then.....
Worker Thread iterates it's queue, executing each request in turn Request Invokes a method on Cache interface (marshall across threads) Cache resolves changes Cache fires event on all of it's listeners UI component changes it's state according to the event fired. "Charles Law" <bl***@nowhere.com> escribió en el mensaje news:Oa**************@TK2MSFTNGP02.phx.gbl...I see what you mean about non-trivial ;-)
I will read and digest. It is the kind of thing that could fit with my scenario.
Thanks.
Charles
"RMT" <no****@nospam.com> wrote in message news:e6*******************@news.demon.co.uk... The data cache is really the central controller of the whole thing, created on the UI thread. It basically mediates between the UI components and the worker thread and the worker thread does all the talking to the database. The thread maintains queues of operations to perform. The data cache adds a request to the queue when something needs to be done, for example:
User clicks ADD RECORD button on a toolbar Code behind the toolbar click tells the cache to ADD RECORD The cache formats a request and queues it at the thread, theThread.AddRequest (theRequest, CRITICAL) ...then forgets about it.
I have 3 queues: CRITICAL, UI and BORED. Critical is for performing operations the user requests, UI is for things like fetching thumbnails (in my application this is a neccessary evil) and BORED is for coherency checking and other stuff like that.
On each iteration of the worker thread loop ( while not m_bFinished () ), it takes the single highest priority item from the list of queues and executes it. If there is nothing in any of the lists, it idles for 100ms (so it doesn't take up all CPU) - after idling it will choose something to check coherency for (in my case the Tree Structure, Thumbnails, etc.) and creates a request, adding it to the BORED queue. Then:
Thread de-queues the single highest priority request Executes it Invokes the result back to the cache The cache resolves changes and fires events to it's listeners. In terms of frequency, I leave this up to the user. You have to trade coherency against network traffic and performance - my application is designed to be able to connect to a webserver via. SOAP or ASP.NET, so it's important I can throttle the coherency check down if I need to.
Note that even with high coherency, the user can still execute an action and have it fail - ie. it's still possible to attempt to modify a record another user has deleted, if you do it before the coherency check works out that the record was deleted. To handle this case, you simply tell the user with an error message, ie. "The record could not be modified because it no longer exists".
It's really a simple pattern but implementation details can be more tricky. If you need any help, post up :). "Charles Law" <bl***@nowhere.com> wrote in message news:ed**************@TK2MSFTNGP05.phx.gbl... Hi
> My pattern uses a worker thread for performing operations, I have my > own data cache, ie. I don't use data sets. The thread checks the cache > in idle time to see if anything has changed and fires off Update, > Delete, Insert and Move (it's a tree structure so I need this one) > methods to it's listeners. UI components (user controls) register > with the data cache as listeners for these kind of events and > implement an IDataUpdateThreadNotification interface.
I might have a go at this; I take your point about the danger of missing a server message. Although it shouldn't happen, I have no doubt that it could.
Have you determined a suitable frequency for checking in your worker thread? Where do you create the data caches, on the UI thread or the worker thread?
Charles
"RMT" <no****@nospam.com> wrote in message news:e6*******************@news.demon.co.uk... > > I am currently implementing a pattern that allows this to happen. It > is actually a non-trivial problem. My pattern uses a worker thread > for performing operations, I have my own data cache, ie. I don't use > data sets. The thread checks the cache in idle time to see if anything > has changed and fires off Update, Delete, Insert and Move (it's a tree > structure so I need this one) methods to it's listeners. UI > components (user controls) register with the data cache as listeners > for these kind of events and implement an > IDataUpdateThreadNotification interface. In actuality, there are over > 60 different kinds of event. Note that the worker thread does not > directly alter the cache, it only reads it, fetches any relevant data > and then invokes a method on the cache object to resolve any changes > that were detected. > > For example, consider I have a set of records in an array, stored in > my cache. The process would look like this: > > (1) Thread is idling, so it decides to do a "coherency check" > (2) Thread creates a data connection and fetches the records > (3) Thread Invokes a method on the cache called "RecordsFetched" > ... > (4) Cache compares all of the time stamps in the fetched records with > the current records and: > > Any timestamps that are different, fires an Updated event to it's > listeners > Any records that exist in the fetched set but not in the cache, > fires an Inserted event to it's listeners > Any records that exist in the cache by not in the fetched set, > fires a Deleted event to it's listeners > > > Anyway, this is the basis I am working from with all of my (somewhat > complex) data structures. Perhaps it's easier with a single data set. > I would definatley avoid any server event notification systems - it's > too easy for your client to miss a message and thereby mess up your > state. > > > > > "Charles Law" <bl***@nowhere.com> wrote in message > news:uY**************@TK2MSFTNGP05.phx.gbl... >> Here's one that should probably have the sub-heading "I'm sure I >> asked this once before, but ...". >> >> Two users are both looking at the same data, from a database. One >> user changes the data and commits it. How does the other user get the >> updated view without polling for changes? Is there some sort of >> callback mechanism that can be set up on the dataset or connection? >> >> TIA >> >> Charles >> >> > >
Yes, I've done a lot of research on this, because my first attempt was a
miserable failure (well it worked, but it hardly produced maintainable code,
so version 2.0 is more comprehensive).
I can have well over 1000,000 rows in my database and performance outside of
the pattern (ie. on the server side with the DMBS) therefore depends on
system admin things like maintenance of indexes and hardware. This is
particularly true for me, because I'm doing a lot of work with binary
blobs - and a tree structure (ie. every row in the table has some
ancestor/descendant/sibling relationship with other records).
Inside of the pattern itself, most operations are more or less
simultaneous - ie. well within the timeframe the user might expect. For
operations that take a long time (seconds, a minute, two minutes), I have a
timer on my main form that is started when the cache handles the
Operation_Started invocation from the thread and stopped when the cache
handles the Operation_Ended invocation from the thread. After one or two
seconds, I display a progress bar. In my experience users don't mind an
operation that takes a while to complete, as long as they can see more or
less how long they have to go fetch a coffee.
Remember that from UI through Cache into Worker Thread and back to UI is
remarkably quick, ie. milliseconds - the time consuming part is database
access - and you can throw hardware at that problem to improve it. Also
because I'm using a worker thread, the UI will remain responsive.
I'm also using DataReaders/Writers, stored procedures for all data access
and the most important structure in .NET (in my opinion), the Dictionary -
so rather than having to hunt through a list of rows to find the one I'm
interested in, I can simply look the record up using a primary key. It's
worth the maintenance for the speedup you get.
"Charles Law" <bl***@nowhere.com> escribió en el mensaje
news:u0**************@TK2MSFTNGP05.phx.gbl... You have obviously taken a comprehensive approach to developing this pattern. Have you found that it is efficient in terms of cpu time? How many rows do you return on an average round-trip? Do you have any metric for the reaction time of the UI to changes in the data?
Charles
"RMT" <no****@nospam.com> wrote in message news:e6*******************@news.demon.co.uk... Well in my case, the implementation details are more complicated, yes - as an example of implementation detail, which I think is specific to my kind of application:
(1) Prioritise Thread Requests (2) Ensure low priority requests don't block high priority ones (3) Error handling in the thread (4) Listeners registering only for the events they are interested in (5) Different types of coherency check (6) Ensure coherency check "chunks", rather than checks an entire structure at once (7) Tree structure - reason about a tree from the flat structure a RDBMS returns (8) Enforce pattern on UI components
But in the simplest case - wanting to keep a record set coherent, it isn't so hard.
Some general principles:
(1) A cache object to store the state you want to persist (2) A worker thread (3) A way for the thread to talk to the cache (Invoking methods on an interface), so (4) An interface for the Cache object to implement so it can receive messages from (3) (5) An abstract class from which your UI components can derive (6) A list of listeners in your Cache Object, i.e. list of references to (5) (7) A base "Operation" class, which encapsulates any operation you perform on the data. (8) Derived classes to actually perform the operations (ie. add, delete, update, etc.) (9) Methods on your data cache that construct objects from (8) and queue them at (2)
Finally, data will flow around the system:
Either:
User interacts with UI component UI component executes a Cache method (ie. "InsertRecord ( aaaabbbb )" ) Cache Object constructs request and adds to worker thread queue
or
Worker thread is in idle time, constructs a coherency check and adds it to it's own queue
and then.....
Worker Thread iterates it's queue, executing each request in turn Request Invokes a method on Cache interface (marshall across threads) Cache resolves changes Cache fires event on all of it's listeners UI component changes it's state according to the event fired. "Charles Law" <bl***@nowhere.com> escribió en el mensaje news:Oa**************@TK2MSFTNGP02.phx.gbl...I see what you mean about non-trivial ;-)
I will read and digest. It is the kind of thing that could fit with my scenario.
Thanks.
Charles
"RMT" <no****@nospam.com> wrote in message news:e6*******************@news.demon.co.uk... The data cache is really the central controller of the whole thing, created on the UI thread. It basically mediates between the UI components and the worker thread and the worker thread does all the talking to the database. The thread maintains queues of operations to perform. The data cache adds a request to the queue when something needs to be done, for example:
User clicks ADD RECORD button on a toolbar Code behind the toolbar click tells the cache to ADD RECORD The cache formats a request and queues it at the thread, theThread.AddRequest (theRequest, CRITICAL) ...then forgets about it.
I have 3 queues: CRITICAL, UI and BORED. Critical is for performing operations the user requests, UI is for things like fetching thumbnails (in my application this is a neccessary evil) and BORED is for coherency checking and other stuff like that.
On each iteration of the worker thread loop ( while not m_bFinished () ), it takes the single highest priority item from the list of queues and executes it. If there is nothing in any of the lists, it idles for 100ms (so it doesn't take up all CPU) - after idling it will choose something to check coherency for (in my case the Tree Structure, Thumbnails, etc.) and creates a request, adding it to the BORED queue. Then:
Thread de-queues the single highest priority request Executes it Invokes the result back to the cache The cache resolves changes and fires events to it's listeners. In terms of frequency, I leave this up to the user. You have to trade coherency against network traffic and performance - my application is designed to be able to connect to a webserver via. SOAP or ASP.NET, so it's important I can throttle the coherency check down if I need to.
Note that even with high coherency, the user can still execute an action and have it fail - ie. it's still possible to attempt to modify a record another user has deleted, if you do it before the coherency check works out that the record was deleted. To handle this case, you simply tell the user with an error message, ie. "The record could not be modified because it no longer exists".
It's really a simple pattern but implementation details can be more tricky. If you need any help, post up :). "Charles Law" <bl***@nowhere.com> wrote in message news:ed**************@TK2MSFTNGP05.phx.gbl... > Hi > >> My pattern uses a worker thread for performing operations, I have my >> own data cache, ie. I don't use data sets. The thread checks the >> cache in idle time to see if anything has changed and fires off >> Update, Delete, Insert and Move (it's a tree structure so I need this >> one) methods to it's listeners. UI components (user controls) >> register with the data cache as listeners for these kind of events >> and implement an IDataUpdateThreadNotification interface. > > I might have a go at this; I take your point about the danger of > missing a server message. Although it shouldn't happen, I have no > doubt that it could. > > Have you determined a suitable frequency for checking in your worker > thread? Where do you create the data caches, on the UI thread or the > worker thread? > > Charles > > > "RMT" <no****@nospam.com> wrote in message > news:e6*******************@news.demon.co.uk... >> >> I am currently implementing a pattern that allows this to happen. It >> is actually a non-trivial problem. My pattern uses a worker thread >> for performing operations, I have my own data cache, ie. I don't use >> data sets. The thread checks the cache in idle time to see if >> anything has changed and fires off Update, Delete, Insert and Move >> (it's a tree structure so I need this one) methods to it's listeners. >> UI components (user controls) register with the data cache as >> listeners for these kind of events and implement an >> IDataUpdateThreadNotification interface. In actuality, there are >> over 60 different kinds of event. Note that the worker thread does >> not directly alter the cache, it only reads it, fetches any relevant >> data and then invokes a method on the cache object to resolve any >> changes that were detected. >> >> For example, consider I have a set of records in an array, stored in >> my cache. The process would look like this: >> >> (1) Thread is idling, so it decides to do a "coherency check" >> (2) Thread creates a data connection and fetches the records >> (3) Thread Invokes a method on the cache called "RecordsFetched" >> ... >> (4) Cache compares all of the time stamps in the fetched records with >> the current records and: >> >> Any timestamps that are different, fires an Updated event to it's >> listeners >> Any records that exist in the fetched set but not in the cache, >> fires an Inserted event to it's listeners >> Any records that exist in the cache by not in the fetched set, >> fires a Deleted event to it's listeners >> >> >> Anyway, this is the basis I am working from with all of my (somewhat >> complex) data structures. Perhaps it's easier with a single data >> set. I would definatley avoid any server event notification systems - >> it's too easy for your client to miss a message and thereby mess up >> your state. >> >> >> >> >> "Charles Law" <bl***@nowhere.com> wrote in message >> news:uY**************@TK2MSFTNGP05.phx.gbl... >>> Here's one that should probably have the sub-heading "I'm sure I >>> asked this once before, but ...". >>> >>> Two users are both looking at the same data, from a database. One >>> user changes the data and commits it. How does the other user get >>> the updated view without polling for changes? Is there some sort of >>> callback mechanism that can be set up on the dataset or connection? >>> >>> TIA >>> >>> Charles >>> >>> >> >> > >
Thanks for all the excellent pointers. This gives me a lot to be going on
with. I will start small, to experiment, and build up, I think.
As you say, you are on V2 now, because V1 was a "miserable failure": was
there anything in particular that you learned to avoid, that in V1 made it
so bad?
Charles
"RMT" <no****@nospam.com> wrote in message
news:e6*******************@news.demon.co.uk... Yes, I've done a lot of research on this, because my first attempt was a miserable failure (well it worked, but it hardly produced maintainable code, so version 2.0 is more comprehensive).
I can have well over 1000,000 rows in my database and performance outside of the pattern (ie. on the server side with the DMBS) therefore depends on system admin things like maintenance of indexes and hardware. This is particularly true for me, because I'm doing a lot of work with binary blobs - and a tree structure (ie. every row in the table has some ancestor/descendant/sibling relationship with other records).
Inside of the pattern itself, most operations are more or less simultaneous - ie. well within the timeframe the user might expect. For operations that take a long time (seconds, a minute, two minutes), I have a timer on my main form that is started when the cache handles the Operation_Started invocation from the thread and stopped when the cache handles the Operation_Ended invocation from the thread. After one or two seconds, I display a progress bar. In my experience users don't mind an operation that takes a while to complete, as long as they can see more or less how long they have to go fetch a coffee.
Remember that from UI through Cache into Worker Thread and back to UI is remarkably quick, ie. milliseconds - the time consuming part is database access - and you can throw hardware at that problem to improve it. Also because I'm using a worker thread, the UI will remain responsive.
I'm also using DataReaders/Writers, stored procedures for all data access and the most important structure in .NET (in my opinion), the Dictionary - so rather than having to hunt through a list of rows to find the one I'm interested in, I can simply look the record up using a primary key. It's worth the maintenance for the speedup you get. "Charles Law" <bl***@nowhere.com> escribió en el mensaje news:u0**************@TK2MSFTNGP05.phx.gbl... You have obviously taken a comprehensive approach to developing this pattern. Have you found that it is efficient in terms of cpu time? How many rows do you return on an average round-trip? Do you have any metric for the reaction time of the UI to changes in the data?
Charles
"RMT" <no****@nospam.com> wrote in message news:e6*******************@news.demon.co.uk... Well in my case, the implementation details are more complicated, yes - as an example of implementation detail, which I think is specific to my kind of application:
(1) Prioritise Thread Requests (2) Ensure low priority requests don't block high priority ones (3) Error handling in the thread (4) Listeners registering only for the events they are interested in (5) Different types of coherency check (6) Ensure coherency check "chunks", rather than checks an entire structure at once (7) Tree structure - reason about a tree from the flat structure a RDBMS returns (8) Enforce pattern on UI components
But in the simplest case - wanting to keep a record set coherent, it isn't so hard.
Some general principles:
(1) A cache object to store the state you want to persist (2) A worker thread (3) A way for the thread to talk to the cache (Invoking methods on an interface), so (4) An interface for the Cache object to implement so it can receive messages from (3) (5) An abstract class from which your UI components can derive (6) A list of listeners in your Cache Object, i.e. list of references to (5) (7) A base "Operation" class, which encapsulates any operation you perform on the data. (8) Derived classes to actually perform the operations (ie. add, delete, update, etc.) (9) Methods on your data cache that construct objects from (8) and queue them at (2)
Finally, data will flow around the system:
Either:
User interacts with UI component UI component executes a Cache method (ie. "InsertRecord ( aaaabbbb )" ) Cache Object constructs request and adds to worker thread queue
or
Worker thread is in idle time, constructs a coherency check and adds it to it's own queue
and then.....
Worker Thread iterates it's queue, executing each request in turn Request Invokes a method on Cache interface (marshall across threads) Cache resolves changes Cache fires event on all of it's listeners UI component changes it's state according to the event fired. "Charles Law" <bl***@nowhere.com> escribió en el mensaje news:Oa**************@TK2MSFTNGP02.phx.gbl... I see what you mean about non-trivial ;-)
I will read and digest. It is the kind of thing that could fit with my scenario.
Thanks.
Charles
"RMT" <no****@nospam.com> wrote in message news:e6*******************@news.demon.co.uk... > The data cache is really the central controller of the whole thing, > created on the UI thread. It basically mediates between the UI > components and the worker thread and the worker thread does all the > talking to the database. The thread maintains queues of operations to > perform. The data cache adds a request to the queue when something > needs to be done, for example: > > > User clicks ADD RECORD button on a toolbar > Code behind the toolbar click tells the cache to ADD RECORD > The cache formats a request and queues it at the thread, > theThread.AddRequest (theRequest, CRITICAL) > ...then forgets about it. > > > I have 3 queues: CRITICAL, UI and BORED. Critical is for performing > operations the user requests, UI is for things like fetching > thumbnails (in my application this is a neccessary evil) and BORED is > for coherency checking and other stuff like that. > > On each iteration of the worker thread loop ( while not m_bFinished > () ), it takes the single highest priority item from the list of > queues and executes it. If there is nothing in any of the lists, it > idles for 100ms (so it doesn't take up all CPU) - after idling it will > choose something to check coherency for (in my case the Tree > Structure, Thumbnails, etc.) and creates a request, adding it to the > BORED queue. Then: > > Thread de-queues the single highest priority request > Executes it > Invokes the result back to the cache > The cache resolves changes and fires events to it's listeners. > > > > In terms of frequency, I leave this up to the user. You have to trade > coherency against network traffic and performance - my application is > designed to be able to connect to a webserver via. SOAP or ASP.NET, so > it's important I can throttle the coherency check down if I need to. > > Note that even with high coherency, the user can still execute an > action and have it fail - ie. it's still possible to attempt to modify > a record another user has deleted, if you do it before the coherency > check works out that the record was deleted. To handle this case, you > simply tell the user with an error message, ie. "The record could not > be modified because it no longer exists". > > > It's really a simple pattern but implementation details can be more > tricky. If you need any help, post up :). > > > > "Charles Law" <bl***@nowhere.com> wrote in message > news:ed**************@TK2MSFTNGP05.phx.gbl... >> Hi >> >>> My pattern uses a worker thread for performing operations, I have my >>> own data cache, ie. I don't use data sets. The thread checks the >>> cache in idle time to see if anything has changed and fires off >>> Update, Delete, Insert and Move (it's a tree structure so I need >>> this one) methods to it's listeners. UI components (user controls) >>> register with the data cache as listeners for these kind of events >>> and implement an IDataUpdateThreadNotification interface. >> >> I might have a go at this; I take your point about the danger of >> missing a server message. Although it shouldn't happen, I have no >> doubt that it could. >> >> Have you determined a suitable frequency for checking in your worker >> thread? Where do you create the data caches, on the UI thread or the >> worker thread? >> >> Charles >> >> >> "RMT" <no****@nospam.com> wrote in message >> news:e6*******************@news.demon.co.uk... >>> >>> I am currently implementing a pattern that allows this to happen. >>> It is actually a non-trivial problem. My pattern uses a worker >>> thread for performing operations, I have my own data cache, ie. I >>> don't use data sets. The thread checks the cache in idle time to see >>> if anything has changed and fires off Update, Delete, Insert and >>> Move (it's a tree structure so I need this one) methods to it's >>> listeners. UI components (user controls) register with the data >>> cache as listeners for these kind of events and implement an >>> IDataUpdateThreadNotification interface. In actuality, there are >>> over 60 different kinds of event. Note that the worker thread does >>> not directly alter the cache, it only reads it, fetches any relevant >>> data and then invokes a method on the cache object to resolve any >>> changes that were detected. >>> >>> For example, consider I have a set of records in an array, stored in >>> my cache. The process would look like this: >>> >>> (1) Thread is idling, so it decides to do a "coherency check" >>> (2) Thread creates a data connection and fetches the records >>> (3) Thread Invokes a method on the cache called "RecordsFetched" >>> ... >>> (4) Cache compares all of the time stamps in the fetched records >>> with the current records and: >>> >>> Any timestamps that are different, fires an Updated event to it's >>> listeners >>> Any records that exist in the fetched set but not in the cache, >>> fires an Inserted event to it's listeners >>> Any records that exist in the cache by not in the fetched set, >>> fires a Deleted event to it's listeners >>> >>> >>> Anyway, this is the basis I am working from with all of my (somewhat >>> complex) data structures. Perhaps it's easier with a single data >>> set. I would definatley avoid any server event notification >>> systems - it's too easy for your client to miss a message and >>> thereby mess up your state. >>> >>> >>> >>> >>> "Charles Law" <bl***@nowhere.com> wrote in message >>> news:uY**************@TK2MSFTNGP05.phx.gbl... >>>> Here's one that should probably have the sub-heading "I'm sure I >>>> asked this once before, but ...". >>>> >>>> Two users are both looking at the same data, from a database. One >>>> user changes the data and commits it. How does the other user get >>>> the updated view without polling for changes? Is there some sort of >>>> callback mechanism that can be set up on the dataset or connection? >>>> >>>> TIA >>>> >>>> Charles >>>> >>>> >>> >>> >> >> > >
Charles,
Most database engines support triggers. They are a special type
of stored procedure that runs when you modify data in a database. I would
add a table to the database which contains 2 fields table name and revision
number. I would create a trigger to update the revision number whenever
something is changed. In a timer check the revision number and reload the
data if necessary. http://msdn.microsoft.com/library/de...thtriggers.asp
Ken
-------------------------
"Charles Law" wrote: Cor
What if the first was looking while the second was on the toilet and did the updates after that while the other one was already not looking anymore. Should there be a message that he/she was on the toilet but changed it?
On return from the lavatory, the user's screen would be up-to-date, that's all.
This kind of pseudo accuratesse is in most situations already long time seen as b*sh*t
By whom? It would seem that Microsoft do not see it that way, as they have introduced the SqlDependency class in VS2005 to address just this situation.
Anyway, I think I have my answer: it is possible only in VS2005 with SqlServer. Thanks.
Charles
"Cor Ligthert [MVP]" <no************@planet.nl> wrote in message news:Of**************@TK2MSFTNGP04.phx.gbl... Charles,
The described process keeps only track for the updating user to prevent that there will not wrong changed data because there where already changes in the meantime.
What if the first was looking while the second was on the toilet and did the updates after that while the other one was already not looking anymore. Should there be a message that he/she was on the toilet but changed it?
This kind of pseudo accuratesse is in most situations already long time seen as b*sh*t
However not there where there are automatic updates done for by instance by a stock exchange.
Ken made this sample for this. Problem for me is that it will not work for me without a 100% load so maybe can you try it as well. Ken has let this tested by others and told that they had not that problem.
http://www.vb-tips.com/default.aspx?...c-3503c15fd46e
Beside this it is of course advisable not to make processes that keeps to long the changes data on the client. However if you are on a place where there is really not any usable connection possible, than it can be that it takes longer.
I hope this helps,
Cor
"Charles Law" <bl***@nowhere.com> schreef in bericht news:u7**************@TK2MSFTNGP05.phx.gbl... Hi Cor
Sorry if I am not catching on very quickly, but I don't quite see how your scenario would work.
A dataset keeps track of the changed rows as long as you did not do acceptchanges.
Isn't this the dataset of the user who has made the changes? What about the dataset of the user who is just viewing the data? Does that get some notification of the changes as well?
In the update process the code checks first row by row of those original rows are changed in the database. (Created new, deleted or updated).
This sounds like something that would happen when the second user tries to make changes, in which case I agree that there would be some sort of error because the data had already changed. But suppose the second user is just looking at the data? Because datasets are disconnected in .NET it seems to me that the second user might never see the changes unless he specifically reloads the data.
Charles
"Cor Ligthert [MVP]" <no************@planet.nl> wrote in message news:uu**************@TK2MSFTNGP02.phx.gbl... Charles,
If you are using any kind of dataadapter/tableadapter and dataset/datatable than it is quiet easy.
A dataset keeps track of the changed rows as long as you did not do acceptchanges.
In the update process the code checks first row by row of those original rows are changed in the database. (Created new, deleted or updated).
If that is the fact than you get a concurrency error. Be aware that accepted rows are handled, so the recovery process is not easy. (Although you can set the connection with a begintransaction and a commit or non commit of that).
Because of the fact that this situations in most situations is seldom, it is called optimistic concurrency. However you have to check it and creates the procedures. Even if that is telling setting everything back to the first state and telling the user to do his job again.
Very simple is it not?
Cor
"Charles Law" <bl***@nowhere.com> schreef in bericht news:uY**************@TK2MSFTNGP05.phx.gbl... > Here's one that should probably have the sub-heading "I'm sure I asked > this once before, but ...". > > Two users are both looking at the same data, from a database. One user > changes the data and commits it. How does the other user get the > updated view without polling for changes? Is there some sort of > callback mechanism that can be set up on the dataset or connection? > > TIA > > Charles > >
Hi Ken
Thanks for the suggestion. I understand the principal of what you are saying
but, to me, it seems akin to using files as semaphores. I am not totally
comfortable with this technique as it is generally a workaround, or even a
kludge. For the moment, I am going to pursue RMT's idea, in the absence of a
native solution (not limited to VS2005 and SqlServer).
Regards
Charles
"Ken Tucker [MVP]" <Ke**********@discussions.microsoft.com> wrote in message
news:4E**********************************@microsof t.com... Charles,
Most database engines support triggers. They are a special type of stored procedure that runs when you modify data in a database. I would add a table to the database which contains 2 fields table name and revision number. I would create a trigger to update the revision number whenever something is changed. In a timer check the revision number and reload the data if necessary.
http://msdn.microsoft.com/library/de...thtriggers.asp
Ken -------------------------
"Charles Law" wrote:
Cor
> What if the first was looking while the second was on the toilet and > did > the updates after that while the other one was already not looking > anymore. Should there be a message that he/she was on the toilet but > changed it?
On return from the lavatory, the user's screen would be up-to-date, that's all.
> This kind of pseudo accuratesse is in most situations already long time > seen as b*sh*t
By whom? It would seem that Microsoft do not see it that way, as they have introduced the SqlDependency class in VS2005 to address just this situation.
Anyway, I think I have my answer: it is possible only in VS2005 with SqlServer. Thanks.
Charles
"Cor Ligthert [MVP]" <no************@planet.nl> wrote in message news:Of**************@TK2MSFTNGP04.phx.gbl... > Charles, > > The described process keeps only track for the updating user to prevent > that there will not wrong changed data because there where already > changes > in the meantime. > > What if the first was looking while the second was on the toilet and > did > the updates after that while the other one was already not looking > anymore. Should there be a message that he/she was on the toilet but > changed it? > > This kind of pseudo accuratesse is in most situations already long time > seen as b*sh*t > > However not there where there are automatic updates done for by > instance > by a stock exchange. > > Ken made this sample for this. Problem for me is that it will not work > for > me without a 100% load so maybe can you try it as well. Ken has let > this > tested by others and told that they had not that problem. > > http://www.vb-tips.com/default.aspx?...c-3503c15fd46e > > Beside this it is of course advisable not to make processes that keeps > to > long the changes data on the client. However if you are on a place > where > there is really not any usable connection possible, than it can be that > it > takes longer. > > I hope this helps, > > Cor > > > "Charles Law" <bl***@nowhere.com> schreef in bericht > news:u7**************@TK2MSFTNGP05.phx.gbl... >> Hi Cor >> >> Sorry if I am not catching on very quickly, but I don't quite see how >> your scenario would work. >> >>> A dataset keeps track of the changed rows as long as you did not do >>> acceptchanges. >> >> Isn't this the dataset of the user who has made the changes? What >> about >> the dataset of the user who is just viewing the data? Does that get >> some >> notification of the changes as well? >> >>> In the update process the code checks first row by row of those >>> original >>> rows are changed in the database. (Created new, deleted or updated). >> >> This sounds like something that would happen when the second user >> tries >> to make changes, in which case I agree that there would be some sort >> of >> error because the data had already changed. But suppose the second >> user >> is just looking at the data? Because datasets are disconnected in .NET >> it >> seems to me that the second user might never see the changes unless he >> specifically reloads the data. >> >> Charles >> >> >> "Cor Ligthert [MVP]" <no************@planet.nl> wrote in message >> news:uu**************@TK2MSFTNGP02.phx.gbl... >>> Charles, >>> >>> If you are using any kind of dataadapter/tableadapter and >>> dataset/datatable than it is quiet easy. >>> >>> A dataset keeps track of the changed rows as long as you did not do >>> acceptchanges. >>> >>> In the update process the code checks first row by row of those >>> original >>> rows are changed in the database. (Created new, deleted or updated). >>> >>> If that is the fact than you get a concurrency error. >>> Be aware that accepted rows are handled, so the recovery process is >>> not >>> easy. >>> (Although you can set the connection with a begintransaction and a >>> commit or non commit of that). >>> >>> Because of the fact that this situations in most situations is >>> seldom, >>> it is called optimistic concurrency. >>> However you have to check it and creates the procedures. >>> Even if that is telling setting everything back to the first state >>> and >>> telling the user to do his job again. >>> >>> Very simple is it not? >>> >>> Cor >>> >>> "Charles Law" <bl***@nowhere.com> schreef in bericht >>> news:uY**************@TK2MSFTNGP05.phx.gbl... >>>> Here's one that should probably have the sub-heading "I'm sure I >>>> asked >>>> this once before, but ...". >>>> >>>> Two users are both looking at the same data, from a database. One >>>> user >>>> changes the data and commits it. How does the other user get the >>>> updated view without polling for changes? Is there some sort of >>>> callback mechanism that can be set up on the dataset or connection? >>>> >>>> TIA >>>> >>>> Charles >>>> >>>> >>> >>> >> >> > >
"Charles Law" wrote: Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
I don't really know much about your architecture, but you could use UDP
multicast messaging. Assuming you have a server that is performing the
updates, once the update is complete, the server could publish a notification
over a multicast address that the data has changed. Clients would obviously
need to join the multicast group.
Depending on how much sophistication you need, the solution can be as simple
or complex as you like. One thing to note is multicast traffic must be
enabled on your network routers, but there is plenty of documentation around
on how it can be done.
HTH
Dan
Charles,
We are currently doing exactly what you desire. We found our solution
using Genine Channels ( www.genuinechannels.com). They have a built in
broadcast engine. Essentially all you do is register MBR's, listener
objects embedded into your business object, into this engine. They
have examples on their site.
Cheers,
Rob Panosh
Advanced Software Designs
Charles Law wrote: Here's one that should probably have the sub-heading "I'm sure I asked this once before, but ...".
Two users are both looking at the same data, from a database. One user changes the data and commits it. How does the other user get the updated view without polling for changes? Is there some sort of callback mechanism that can be set up on the dataset or connection?
TIA
Charles
Yes, definately. I learned that the UI should be completely separated from
anything that changes state. A lot of sample code you see shows "on button
press event, modify the record in the database". This is totally wrong.
The more you do state change stuff in your UI components, the more of a mess
you will eventually get into trying to keep them coherent. The correct way
to think about it is:
UI event the user would like to do something that changes the state (modify
a record for example
<some object that caches the state> asks a thread to change the state
The thread changes the state
The thread notifies the cache the state has changed
The cache notifies the UI the state has changed
rather than:
Private Sub ToolBar1_ButtonClick(ByVal sender As System.Object, ByVal e As
System.Windows.Forms.ToolBarButtonClickEventArgs) Handles
ToolBar1.ButtonClick
If e.Button Is TheTriggerHappyButton Then
WhoooohooooWildlyChangeStuffInTheDatabase()
End If
End Sub
"Charles Law" <bl***@nowhere.com> escribió en el mensaje
news:es**************@TK2MSFTNGP04.phx.gbl... Thanks for all the excellent pointers. This gives me a lot to be going on with. I will start small, to experiment, and build up, I think.
As you say, you are on V2 now, because V1 was a "miserable failure": was there anything in particular that you learned to avoid, that in V1 made it so bad?
Charles
"RMT" <no****@nospam.com> wrote in message news:e6*******************@news.demon.co.uk... Yes, I've done a lot of research on this, because my first attempt was a miserable failure (well it worked, but it hardly produced maintainable code, so version 2.0 is more comprehensive).
I can have well over 1000,000 rows in my database and performance outside of the pattern (ie. on the server side with the DMBS) therefore depends on system admin things like maintenance of indexes and hardware. This is particularly true for me, because I'm doing a lot of work with binary blobs - and a tree structure (ie. every row in the table has some ancestor/descendant/sibling relationship with other records).
Inside of the pattern itself, most operations are more or less simultaneous - ie. well within the timeframe the user might expect. For operations that take a long time (seconds, a minute, two minutes), I have a timer on my main form that is started when the cache handles the Operation_Started invocation from the thread and stopped when the cache handles the Operation_Ended invocation from the thread. After one or two seconds, I display a progress bar. In my experience users don't mind an operation that takes a while to complete, as long as they can see more or less how long they have to go fetch a coffee.
Remember that from UI through Cache into Worker Thread and back to UI is remarkably quick, ie. milliseconds - the time consuming part is database access - and you can throw hardware at that problem to improve it. Also because I'm using a worker thread, the UI will remain responsive.
I'm also using DataReaders/Writers, stored procedures for all data access and the most important structure in .NET (in my opinion), the Dictionary - so rather than having to hunt through a list of rows to find the one I'm interested in, I can simply look the record up using a primary key. It's worth the maintenance for the speedup you get. "Charles Law" <bl***@nowhere.com> escribió en el mensaje news:u0**************@TK2MSFTNGP05.phx.gbl... You have obviously taken a comprehensive approach to developing this pattern. Have you found that it is efficient in terms of cpu time? How many rows do you return on an average round-trip? Do you have any metric for the reaction time of the UI to changes in the data?
Charles
"RMT" <no****@nospam.com> wrote in message news:e6*******************@news.demon.co.uk... Well in my case, the implementation details are more complicated, yes - as an example of implementation detail, which I think is specific to my kind of application:
(1) Prioritise Thread Requests (2) Ensure low priority requests don't block high priority ones (3) Error handling in the thread (4) Listeners registering only for the events they are interested in (5) Different types of coherency check (6) Ensure coherency check "chunks", rather than checks an entire structure at once (7) Tree structure - reason about a tree from the flat structure a RDBMS returns (8) Enforce pattern on UI components
But in the simplest case - wanting to keep a record set coherent, it isn't so hard.
Some general principles:
(1) A cache object to store the state you want to persist (2) A worker thread (3) A way for the thread to talk to the cache (Invoking methods on an interface), so (4) An interface for the Cache object to implement so it can receive messages from (3) (5) An abstract class from which your UI components can derive (6) A list of listeners in your Cache Object, i.e. list of references to (5) (7) A base "Operation" class, which encapsulates any operation you perform on the data. (8) Derived classes to actually perform the operations (ie. add, delete, update, etc.) (9) Methods on your data cache that construct objects from (8) and queue them at (2)
Finally, data will flow around the system:
Either:
User interacts with UI component UI component executes a Cache method (ie. "InsertRecord ( aaaabbbb )" ) Cache Object constructs request and adds to worker thread queue
or
Worker thread is in idle time, constructs a coherency check and adds it to it's own queue
and then.....
Worker Thread iterates it's queue, executing each request in turn Request Invokes a method on Cache interface (marshall across threads) Cache resolves changes Cache fires event on all of it's listeners UI component changes it's state according to the event fired. "Charles Law" <bl***@nowhere.com> escribió en el mensaje news:Oa**************@TK2MSFTNGP02.phx.gbl... >I see what you mean about non-trivial ;-) > > I will read and digest. It is the kind of thing that could fit with my > scenario. > > Thanks. > > Charles > > > "RMT" <no****@nospam.com> wrote in message > news:e6*******************@news.demon.co.uk... >> The data cache is really the central controller of the whole thing, >> created on the UI thread. It basically mediates between the UI >> components and the worker thread and the worker thread does all the >> talking to the database. The thread maintains queues of operations to >> perform. The data cache adds a request to the queue when something >> needs to be done, for example: >> >> >> User clicks ADD RECORD button on a toolbar >> Code behind the toolbar click tells the cache to ADD RECORD >> The cache formats a request and queues it at the thread, >> theThread.AddRequest (theRequest, CRITICAL) >> ...then forgets about it. >> >> >> I have 3 queues: CRITICAL, UI and BORED. Critical is for performing >> operations the user requests, UI is for things like fetching >> thumbnails (in my application this is a neccessary evil) and BORED is >> for coherency checking and other stuff like that. >> >> On each iteration of the worker thread loop ( while not m_bFinished >> () ), it takes the single highest priority item from the list of >> queues and executes it. If there is nothing in any of the lists, it >> idles for 100ms (so it doesn't take up all CPU) - after idling it >> will choose something to check coherency for (in my case the Tree >> Structure, Thumbnails, etc.) and creates a request, adding it to the >> BORED queue. Then: >> >> Thread de-queues the single highest priority request >> Executes it >> Invokes the result back to the cache >> The cache resolves changes and fires events to it's listeners. >> >> >> >> In terms of frequency, I leave this up to the user. You have to >> trade coherency against network traffic and performance - my >> application is designed to be able to connect to a webserver via. >> SOAP or ASP.NET, so it's important I can throttle the coherency check >> down if I need to. >> >> Note that even with high coherency, the user can still execute an >> action and have it fail - ie. it's still possible to attempt to >> modify a record another user has deleted, if you do it before the >> coherency check works out that the record was deleted. To handle >> this case, you simply tell the user with an error message, ie. "The >> record could not be modified because it no longer exists". >> >> >> It's really a simple pattern but implementation details can be more >> tricky. If you need any help, post up :). >> >> >> >> "Charles Law" <bl***@nowhere.com> wrote in message >> news:ed**************@TK2MSFTNGP05.phx.gbl... >>> Hi >>> >>>> My pattern uses a worker thread for performing operations, I have >>>> my own data cache, ie. I don't use data sets. The thread checks the >>>> cache in idle time to see if anything has changed and fires off >>>> Update, Delete, Insert and Move (it's a tree structure so I need >>>> this one) methods to it's listeners. UI components (user controls) >>>> register with the data cache as listeners for these kind of events >>>> and implement an IDataUpdateThreadNotification interface. >>> >>> I might have a go at this; I take your point about the danger of >>> missing a server message. Although it shouldn't happen, I have no >>> doubt that it could. >>> >>> Have you determined a suitable frequency for checking in your worker >>> thread? Where do you create the data caches, on the UI thread or the >>> worker thread? >>> >>> Charles >>> >>> >>> "RMT" <no****@nospam.com> wrote in message >>> news:e6*******************@news.demon.co.uk... >>>> >>>> I am currently implementing a pattern that allows this to happen. >>>> It is actually a non-trivial problem. My pattern uses a worker >>>> thread for performing operations, I have my own data cache, ie. I >>>> don't use data sets. The thread checks the cache in idle time to >>>> see if anything has changed and fires off Update, Delete, Insert >>>> and Move (it's a tree structure so I need this one) methods to it's >>>> listeners. UI components (user controls) register with the data >>>> cache as listeners for these kind of events and implement an >>>> IDataUpdateThreadNotification interface. In actuality, there are >>>> over 60 different kinds of event. Note that the worker thread does >>>> not directly alter the cache, it only reads it, fetches any >>>> relevant data and then invokes a method on the cache object to >>>> resolve any changes that were detected. >>>> >>>> For example, consider I have a set of records in an array, stored >>>> in my cache. The process would look like this: >>>> >>>> (1) Thread is idling, so it decides to do a "coherency check" >>>> (2) Thread creates a data connection and fetches the records >>>> (3) Thread Invokes a method on the cache called "RecordsFetched" >>>> ... >>>> (4) Cache compares all of the time stamps in the fetched records >>>> with the current records and: >>>> >>>> Any timestamps that are different, fires an Updated event to >>>> it's listeners >>>> Any records that exist in the fetched set but not in the cache, >>>> fires an Inserted event to it's listeners >>>> Any records that exist in the cache by not in the fetched set, >>>> fires a Deleted event to it's listeners >>>> >>>> >>>> Anyway, this is the basis I am working from with all of my >>>> (somewhat complex) data structures. Perhaps it's easier with a >>>> single data set. I would definatley avoid any server event >>>> notification systems - it's too easy for your client to miss a >>>> message and thereby mess up your state. >>>> >>>> >>>> >>>> >>>> "Charles Law" <bl***@nowhere.com> wrote in message >>>> news:uY**************@TK2MSFTNGP05.phx.gbl... >>>>> Here's one that should probably have the sub-heading "I'm sure I >>>>> asked this once before, but ...". >>>>> >>>>> Two users are both looking at the same data, from a database. One >>>>> user changes the data and commits it. How does the other user get >>>>> the updated view without polling for changes? Is there some sort >>>>> of callback mechanism that can be set up on the dataset or >>>>> connection? >>>>> >>>>> TIA >>>>> >>>>> Charles >>>>> >>>>> >>>> >>>> >>> >>> >> >> > >
I can see exactly how that is going to work for some of the screens I have,
since there is a summary at the top, and a data entry card at the bottom. If
I change the data behind the Enter button on the card, the summary will not
reflect the change unless I change that as well. Far better to have the
summary 'notified' of the change by the thread that updates the database.
It always helps to talk these things through with someone ;-)
Cheers.
Charles
"RMT" <no****@nospam.com> wrote in message
news:e6*******************@news.demon.co.uk... Yes, definately. I learned that the UI should be completely separated from anything that changes state. A lot of sample code you see shows "on button press event, modify the record in the database". This is totally wrong. The more you do state change stuff in your UI components, the more of a mess you will eventually get into trying to keep them coherent. The correct way to think about it is:
UI event the user would like to do something that changes the state (modify a record for example <some object that caches the state> asks a thread to change the state The thread changes the state The thread notifies the cache the state has changed The cache notifies the UI the state has changed rather than: Private Sub ToolBar1_ButtonClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ToolBarButtonClickEventArgs) Handles ToolBar1.ButtonClick
If e.Button Is TheTriggerHappyButton Then
WhoooohooooWildlyChangeStuffInTheDatabase()
End If
End Sub
"Charles Law" <bl***@nowhere.com> escribió en el mensaje news:es**************@TK2MSFTNGP04.phx.gbl... Thanks for all the excellent pointers. This gives me a lot to be going on with. I will start small, to experiment, and build up, I think.
As you say, you are on V2 now, because V1 was a "miserable failure": was there anything in particular that you learned to avoid, that in V1 made it so bad?
Charles
"RMT" <no****@nospam.com> wrote in message news:e6*******************@news.demon.co.uk... Yes, I've done a lot of research on this, because my first attempt was a miserable failure (well it worked, but it hardly produced maintainable code, so version 2.0 is more comprehensive).
I can have well over 1000,000 rows in my database and performance outside of the pattern (ie. on the server side with the DMBS) therefore depends on system admin things like maintenance of indexes and hardware. This is particularly true for me, because I'm doing a lot of work with binary blobs - and a tree structure (ie. every row in the table has some ancestor/descendant/sibling relationship with other records).
Inside of the pattern itself, most operations are more or less simultaneous - ie. well within the timeframe the user might expect. For operations that take a long time (seconds, a minute, two minutes), I have a timer on my main form that is started when the cache handles the Operation_Started invocation from the thread and stopped when the cache handles the Operation_Ended invocation from the thread. After one or two seconds, I display a progress bar. In my experience users don't mind an operation that takes a while to complete, as long as they can see more or less how long they have to go fetch a coffee.
Remember that from UI through Cache into Worker Thread and back to UI is remarkably quick, ie. milliseconds - the time consuming part is database access - and you can throw hardware at that problem to improve it. Also because I'm using a worker thread, the UI will remain responsive.
I'm also using DataReaders/Writers, stored procedures for all data access and the most important structure in .NET (in my opinion), the Dictionary - so rather than having to hunt through a list of rows to find the one I'm interested in, I can simply look the record up using a primary key. It's worth the maintenance for the speedup you get. "Charles Law" <bl***@nowhere.com> escribió en el mensaje news:u0**************@TK2MSFTNGP05.phx.gbl... You have obviously taken a comprehensive approach to developing this pattern. Have you found that it is efficient in terms of cpu time? How many rows do you return on an average round-trip? Do you have any metric for the reaction time of the UI to changes in the data?
Charles
"RMT" <no****@nospam.com> wrote in message news:e6*******************@news.demon.co.uk... > Well in my case, the implementation details are more complicated, > yes - as an example of implementation detail, which I think is > specific to my kind of application: > > (1) Prioritise Thread Requests > (2) Ensure low priority requests don't block high priority ones > (3) Error handling in the thread > (4) Listeners registering only for the events they are interested in > (5) Different types of coherency check > (6) Ensure coherency check "chunks", rather than checks an entire > structure at once > (7) Tree structure - reason about a tree from the flat structure a > RDBMS returns > (8) Enforce pattern on UI components > > > But in the simplest case - wanting to keep a record set coherent, it > isn't so hard. > > > Some general principles: > > (1) A cache object to store the state you want to persist > (2) A worker thread > (3) A way for the thread to talk to the cache (Invoking methods on an > interface), so > (4) An interface for the Cache object to implement so it can receive > messages from (3) > (5) An abstract class from which your UI components can derive > (6) A list of listeners in your Cache Object, i.e. list of references > to (5) > (7) A base "Operation" class, which encapsulates any operation you > perform on the data. > (8) Derived classes to actually perform the operations (ie. add, > delete, update, etc.) > (9) Methods on your data cache that construct objects from (8) and > queue them at (2) > > Finally, data will flow around the system: > > Either: > > User interacts with UI component > UI component executes a Cache method (ie. "InsertRecord ( > aaaabbbb )" ) > Cache Object constructs request and adds to worker thread queue > > or > > Worker thread is in idle time, constructs a coherency check and adds > it to it's own queue > > and then..... > > Worker Thread iterates it's queue, executing each request in turn > Request Invokes a method on Cache interface (marshall across threads) > Cache resolves changes > Cache fires event on all of it's listeners > UI component changes it's state according to the event fired. > > > > > > > "Charles Law" <bl***@nowhere.com> escribió en el mensaje > news:Oa**************@TK2MSFTNGP02.phx.gbl... >>I see what you mean about non-trivial ;-) >> >> I will read and digest. It is the kind of thing that could fit with >> my scenario. >> >> Thanks. >> >> Charles >> >> >> "RMT" <no****@nospam.com> wrote in message >> news:e6*******************@news.demon.co.uk... >>> The data cache is really the central controller of the whole thing, >>> created on the UI thread. It basically mediates between the UI >>> components and the worker thread and the worker thread does all the >>> talking to the database. The thread maintains queues of operations >>> to perform. The data cache adds a request to the queue when >>> something needs to be done, for example: >>> >>> >>> User clicks ADD RECORD button on a toolbar >>> Code behind the toolbar click tells the cache to ADD RECORD >>> The cache formats a request and queues it at the thread, >>> theThread.AddRequest (theRequest, CRITICAL) >>> ...then forgets about it. >>> >>> >>> I have 3 queues: CRITICAL, UI and BORED. Critical is for >>> performing operations the user requests, UI is for things like >>> fetching thumbnails (in my application this is a neccessary evil) >>> and BORED is for coherency checking and other stuff like that. >>> >>> On each iteration of the worker thread loop ( while not m_bFinished >>> () ), it takes the single highest priority item from the list of >>> queues and executes it. If there is nothing in any of the lists, it >>> idles for 100ms (so it doesn't take up all CPU) - after idling it >>> will choose something to check coherency for (in my case the Tree >>> Structure, Thumbnails, etc.) and creates a request, adding it to the >>> BORED queue. Then: >>> >>> Thread de-queues the single highest priority request >>> Executes it >>> Invokes the result back to the cache >>> The cache resolves changes and fires events to it's listeners. >>> >>> >>> >>> In terms of frequency, I leave this up to the user. You have to >>> trade coherency against network traffic and performance - my >>> application is designed to be able to connect to a webserver via. >>> SOAP or ASP.NET, so it's important I can throttle the coherency >>> check down if I need to. >>> >>> Note that even with high coherency, the user can still execute an >>> action and have it fail - ie. it's still possible to attempt to >>> modify a record another user has deleted, if you do it before the >>> coherency check works out that the record was deleted. To handle >>> this case, you simply tell the user with an error message, ie. "The >>> record could not be modified because it no longer exists". >>> >>> >>> It's really a simple pattern but implementation details can be more >>> tricky. If you need any help, post up :). >>> >>> >>> >>> "Charles Law" <bl***@nowhere.com> wrote in message >>> news:ed**************@TK2MSFTNGP05.phx.gbl... >>>> Hi >>>> >>>>> My pattern uses a worker thread for performing operations, I have >>>>> my own data cache, ie. I don't use data sets. The thread checks >>>>> the cache in idle time to see if anything has changed and fires >>>>> off Update, Delete, Insert and Move (it's a tree structure so I >>>>> need this one) methods to it's listeners. UI components (user >>>>> controls) register with the data cache as listeners for these kind >>>>> of events and implement an IDataUpdateThreadNotification >>>>> interface. >>>> >>>> I might have a go at this; I take your point about the danger of >>>> missing a server message. Although it shouldn't happen, I have no >>>> doubt that it could. >>>> >>>> Have you determined a suitable frequency for checking in your >>>> worker thread? Where do you create the data caches, on the UI >>>> thread or the worker thread? >>>> >>>> Charles >>>> >>>> >>>> "RMT" <no****@nospam.com> wrote in message >>>> news:e6*******************@news.demon.co.uk... >>>>> >>>>> I am currently implementing a pattern that allows this to happen. >>>>> It is actually a non-trivial problem. My pattern uses a worker >>>>> thread for performing operations, I have my own data cache, ie. I >>>>> don't use data sets. The thread checks the cache in idle time to >>>>> see if anything has changed and fires off Update, Delete, Insert >>>>> and Move (it's a tree structure so I need this one) methods to >>>>> it's listeners. UI components (user controls) register with the >>>>> data cache as listeners for these kind of events and implement an >>>>> IDataUpdateThreadNotification interface. In actuality, there are >>>>> over 60 different kinds of event. Note that the worker thread does >>>>> not directly alter the cache, it only reads it, fetches any >>>>> relevant data and then invokes a method on the cache object to >>>>> resolve any changes that were detected. >>>>> >>>>> For example, consider I have a set of records in an array, stored >>>>> in my cache. The process would look like this: >>>>> >>>>> (1) Thread is idling, so it decides to do a "coherency check" >>>>> (2) Thread creates a data connection and fetches the records >>>>> (3) Thread Invokes a method on the cache called "RecordsFetched" >>>>> ... >>>>> (4) Cache compares all of the time stamps in the fetched records >>>>> with the current records and: >>>>> >>>>> Any timestamps that are different, fires an Updated event to >>>>> it's listeners >>>>> Any records that exist in the fetched set but not in the cache, >>>>> fires an Inserted event to it's listeners >>>>> Any records that exist in the cache by not in the fetched set, >>>>> fires a Deleted event to it's listeners >>>>> >>>>> >>>>> Anyway, this is the basis I am working from with all of my >>>>> (somewhat complex) data structures. Perhaps it's easier with a >>>>> single data set. I would definatley avoid any server event >>>>> notification systems - it's too easy for your client to miss a >>>>> message and thereby mess up your state. >>>>> >>>>> >>>>> >>>>> >>>>> "Charles Law" <bl***@nowhere.com> wrote in message >>>>> news:uY**************@TK2MSFTNGP05.phx.gbl... >>>>>> Here's one that should probably have the sub-heading "I'm sure I >>>>>> asked this once before, but ...". >>>>>> >>>>>> Two users are both looking at the same data, from a database. One >>>>>> user changes the data and commits it. How does the other user get >>>>>> the updated view without polling for changes? Is there some sort >>>>>> of callback mechanism that can be set up on the dataset or >>>>>> connection? >>>>>> >>>>>> TIA >>>>>> >>>>>> Charles >>>>>> >>>>>> >>>>> >>>>> >>>> >>>> >>> >>> >> >> > >
This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Christopher Koh |
last post by:
how do you stop Access from saving any changed data in your tables and
queries?
like i just add or change data on the table/query tables,then click on
X (exit)because i have no intention of saving...
|
by: Charles Law |
last post by:
Here's one that should probably have the sub-heading "I'm sure I asked this
once before, but ...".
Two users are both looking at the same data, from a database. One user
changes the data and...
|
by: DJRhino |
last post by:
Was curious if anyone else was having this same issue or not....
I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM)
The start time is equivalent to 19:00 (7PM) in Central...
|
by: Aliciasmith |
last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
|
by: giovanniandrean |
last post by:
The energy model is structured as follows and uses excel sheets to give input data:
1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM)
Please note that the UK and Europe revert to winter time on...
|
by: nia12 |
last post by:
Hi there,
I am very new to Access so apologies if any of this is obvious/not clear.
I am creating a data collection tool for health care employees to complete. It consists of a number of...
|
by: NeoPa |
last post by:
Introduction
For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
|
by: isladogs |
last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, Mike...
|
by: GKJR |
last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...
| |