Home All Groups Group Topic Archive Search About

multithreaded grid-binding problems

Author
3 Nov 2005 11:24 PM
Daniel Serra
Hi there (sorry for the cross-post),

I have a problem that I am not sure quite how to resolve. I have a series of
datasets, with grids being bound to any one of the datasets. These datasets
can get updated quite frequently (upwards of 10-20x per second, sometimes
just once a second), with each update often involving multiple row
addition/deletion as well updates. Originally I had the datasets created in
the same thread as the UI, which worked fine, but was a dog. What I would
like to do is have the dataset updates happen on another thread, and have
the grids show changes only once every 1/4 second (in effect throttling the
updates and allow for a more responsive UI). I have had limited success with
this as grid data sometimes seems to go missing, and was wondering if
anybody has had any experience in dealing with rapidly changing bound grids,
and if so what approaches you took?

Cheers

Author
4 Nov 2005 4:46 AM
Manoj G [MVP]
Hi Daniel,

Are you updating the UI controls (binding ) on the right thread? If not, you
should be updating the UI controls on the thread that created them, by means
of calling Control.Invoke.

HTH,
Manoj G
MVP, Visual Developer
http://msmvps.com/manoj

Show quote
"Daniel Serra" <d.serra@avoidspam.com> wrote in message
news:OQLWN3M4FHA.696@TK2MSFTNGP09.phx.gbl...
> Hi there (sorry for the cross-post),
>
> I have a problem that I am not sure quite how to resolve. I have a series
> of datasets, with grids being bound to any one of the datasets. These
> datasets can get updated quite frequently (upwards of 10-20x per second,
> sometimes just once a second), with each update often involving multiple
> row addition/deletion as well updates. Originally I had the datasets
> created in the same thread as the UI, which worked fine, but was a dog.
> What I would like to do is have the dataset updates happen on another
> thread, and have the grids show changes only once every 1/4 second (in
> effect throttling the updates and allow for a more responsive UI). I have
> had limited success with this as grid data sometimes seems to go missing,
> and was wondering if anybody has had any experience in dealing with
> rapidly changing bound grids, and if so what approaches you took?
>
> Cheers
>
>
Author
4 Nov 2005 1:31 PM
Daniel Serra
yes, I did. I passed in a copy of the GetChanges in any event,
control.invoked and then merged the changes to the actual bound dataset

Show quote
"Manoj G [MVP]" <manoj@nospam.com> wrote in message
news:uA89KrP4FHA.1276@TK2MSFTNGP09.phx.gbl...
> Hi Daniel,
>
> Are you updating the UI controls (binding ) on the right thread? If not,
> you should be updating the UI controls on the thread that created them, by
> means of calling Control.Invoke.
>
> HTH,
> Manoj G
> MVP, Visual Developer
> http://msmvps.com/manoj
>
> "Daniel Serra" <d.serra@avoidspam.com> wrote in message
> news:OQLWN3M4FHA.696@TK2MSFTNGP09.phx.gbl...
>> Hi there (sorry for the cross-post),
>>
>> I have a problem that I am not sure quite how to resolve. I have a series
>> of datasets, with grids being bound to any one of the datasets. These
>> datasets can get updated quite frequently (upwards of 10-20x per second,
>> sometimes just once a second), with each update often involving multiple
>> row addition/deletion as well updates. Originally I had the datasets
>> created in the same thread as the UI, which worked fine, but was a dog.
>> What I would like to do is have the dataset updates happen on another
>> thread, and have the grids show changes only once every 1/4 second (in
>> effect throttling the updates and allow for a more responsive UI). I have
>> had limited success with this as grid data sometimes seems to go missing,
>> and was wondering if anybody has had any experience in dealing with
>> rapidly changing bound grids, and if so what approaches you took?
>>
>> Cheers
>>
>>
>
>
Author
6 Nov 2005 12:44 PM
TT (Tom Tempelaere)
Hi Daniel,

Show quote
"Daniel Serra" <d.serra@avoidspam.com> schreef in bericht
news:OQLWN3M4FHA.696@TK2MSFTNGP09.phx.gbl...
> Hi there (sorry for the cross-post),
>
> I have a problem that I am not sure quite how to resolve. I have a series
> of datasets, with grids being bound to any one of the datasets. These
> datasets can get updated quite frequently (upwards of 10-20x per second,
> sometimes just once a second), with each update often involving multiple
> row addition/deletion as well updates. Originally I had the datasets
> created in the same thread as the UI, which worked fine, but was a dog.
> What I would like to do is have the dataset updates happen on another
> thread, and have the grids show changes only once every 1/4 second (in
> effect throttling the updates and allow for a more responsive UI). I have
> had limited success with this as grid data sometimes seems to go missing,
> and was wondering if anybody has had any experience in dealing with
> rapidly changing bound grids, and if so what approaches you took?
> Cheers

I have a similar situation, where I use a producer/consumer pattern. The
producer adds rows to a list, and a timer adds the rows from the list to the
grid by invoking a method that adds the rows. The reason I did this is
because of poor performance; DataGrid has a lot of events triggering and
updates going on if each row is added seperately (eats CPU time).

So basically what you need:
    - a shared container that stores the produced rows
    - a producer thread that adds the produced rows to the container
    - a timer undocks the rows from the container (if any), and invokes a
method that adds these rows to the grid

Do not forget to synchronize access to the shared container. The timer
should undock the rows in the container, and invoke a method that adds the
rows to the grid. This method that adds the rows should do the following
before adding the rows:
    - SuspendLayout on the DataGrid
    - BeginLoadData on the DataTable
And do the following after adding the rows:
    - EndLoadData on the DataTable
    - ResumeLayout on the DataGrid

I chose the same timer interval as you did (250ms).

Hope this helps,
Tom Tempelaere.
Author
7 Nov 2005 1:23 PM
Daniel Serra
Hi Tom,

Sounds like a great idea. However, how do you deal with deleted rows in the
case below? In the meantime I will try out the solution you describe below.
Cheers!

Show quote
:D

"TT (Tom Tempelaere)" </\/_0_$P@/\/\titi____AThotmailD.Tcom/\/\@P$_0_/\/>
wrote in message news:6Vmbf.40820$OI1.2044026@phobos.telenet-ops.be...
> Hi Daniel,
>
> "Daniel Serra" <d.serra@avoidspam.com> schreef in bericht
> news:OQLWN3M4FHA.696@TK2MSFTNGP09.phx.gbl...
>> Hi there (sorry for the cross-post),
>>
>> I have a problem that I am not sure quite how to resolve. I have a series
>> of datasets, with grids being bound to any one of the datasets. These
>> datasets can get updated quite frequently (upwards of 10-20x per second,
>> sometimes just once a second), with each update often involving multiple
>> row addition/deletion as well updates. Originally I had the datasets
>> created in the same thread as the UI, which worked fine, but was a dog.
>> What I would like to do is have the dataset updates happen on another
>> thread, and have the grids show changes only once every 1/4 second (in
>> effect throttling the updates and allow for a more responsive UI). I have
>> had limited success with this as grid data sometimes seems to go missing,
>> and was wondering if anybody has had any experience in dealing with
>> rapidly changing bound grids, and if so what approaches you took?
>> Cheers
>
> I have a similar situation, where I use a producer/consumer pattern. The
> producer adds rows to a list, and a timer adds the rows from the list to
> the grid by invoking a method that adds the rows. The reason I did this is
> because of poor performance; DataGrid has a lot of events triggering and
> updates going on if each row is added seperately (eats CPU time).
>
> So basically what you need:
>    - a shared container that stores the produced rows
>    - a producer thread that adds the produced rows to the container
>    - a timer undocks the rows from the container (if any), and invokes a
> method that adds these rows to the grid
>
> Do not forget to synchronize access to the shared container. The timer
> should undock the rows in the container, and invoke a method that adds the
> rows to the grid. This method that adds the rows should do the following
> before adding the rows:
>    - SuspendLayout on the DataGrid
>    - BeginLoadData on the DataTable
> And do the following after adding the rows:
>    - EndLoadData on the DataTable
>    - ResumeLayout on the DataGrid
>
> I chose the same timer interval as you did (250ms).
>
> Hope this helps,
> Tom Tempelaere.
>
Author
9 Nov 2005 5:10 PM
TT (Tom Tempelaere)
Hi Daniel,

"Daniel Serra" wrote:
> Sounds like a great idea. However, how do you deal with deleted rows in the
> case below? In the meantime I will try out the solution you describe below.
> Cheers!

I'll describe the control I made in which I used the pattern I described.
The control is a logging control that uses DataGrid for showing the logged
rows. Because DataGrid becomes slow if there are too many rows in the
DataTable bound to it, I restrict the number of rows that can appear.

Remember the method that adds the rows to the DataTable bound to the
DataGrid (the method that is invoked from the timer to effectively add the
rows). Also remember that I said to first call SuspendLayout (DataGrid) and
BeginLoadData (bound DataTable) before adding the rows. Well, the place where
you would add the rows, you would also delete the rows that should be deleted.

To illustrate, suppose my logging control has a maximum of 2000 entries, it
contains 1995 entries, and the timer finds 105 rows to be added to the
logging control. Before adding (appending) the 105 rows, I first delete the
first 100 rows in the DataTable then afterwards I add the 105 rows (yielding
a DataTable with exactly 2000 rows).

I'll rephrase my suggestion from my previous post:
" This method that adds/deletes rows should do the following before
adding/deleting the rows:
   - SuspendLayout on the DataGrid
   - BeginLoadData on the DataTable
And do the following after adding/deleting the rows:
   - EndLoadData on the DataTable
   - ResumeLayout on the DataGrid "

Hope this helps & kind regards,
--
Tom Tempelaere.
Author
9 Nov 2005 5:15 PM
TT (Tom Tempelaere)
Hi again Daniel,

Show quote
"TT (Tom Tempelaere)" wrote:
>
> "Daniel Serra" wrote:
> > Sounds like a great idea. However, how do you deal with deleted rows in the
> > case below? In the meantime I will try out the solution you describe below.
> > Cheers!
>
[...]

> Remember the method that adds the rows to the DataTable bound to the
> DataGrid (the method that is invoked from the timer to effectively add the
> rows). Also remember that I said to first call SuspendLayout (DataGrid) and
> BeginLoadData (bound DataTable) before adding the rows. Well, the place where
> you would add the rows, you would also delete the rows that should be deleted.
[...]

Also note that for performance reasons, it is better to first delete the
rows, and then add the rows, well, at least it is better in my scenario but I
think it is generally the better way.

Kind regards,
--
Tom Tempelaere

AddThis Social Bookmark Button