[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.dotnet.framework

WindowsFormsSynchronizationContext.Send: how does the delegate provided to this method interact with the control's message pump?

eugen_nw

8/14/2008 12:17:00 AM

I did look under the hood and this method is calling
Control.Invoke(). Digging deeper down I've stopped at the
RuntimeMethodHandle._InvokeMethodFast() method whose code I cannot
find.

I know that the delegates invoked via Control.BeginInvoke() will use
the window's message pump to send and retrieve the delegate and its
arguments, so the control/form will not react to Windows messages
while it is executing the delegate. That is the behavior I want to
have as well when the delegate passed to
WindowsFormsSynchronizationContext.Send() executes.

For a bit of a background, I want to have this behavior in order to
make sure that a grid control will not repaint itself while I'm re-
populating the DataTable it is bound to. If you have other
suggestions on how to ensure that the grid will not read from the
DataTable at the same time a worker thread reloads it, please send
them my way.


Thanks much, eugen
4 Answers

eugen_nw

8/14/2008 12:55:00 AM

0

I wasn't very clear in the last paragraph of my original post: I'm
using a different thread to run the query that populates the DataTable
the grid is bound to and bad things happen if the grid in the UI
thread tries to read from the DataTable at the same time the
DataAdapter.Fill method populates it on the worker thread.

Peter Duniho

8/14/2008 1:29:00 AM

0

On Wed, 13 Aug 2008 17:17:13 -0700, eugen_nw
<eugen_newsgroups@hotmail.com> wrote:

> I did look under the hood and this method is calling
> Control.Invoke(). Digging deeper down I've stopped at the
> RuntimeMethodHandle._InvokeMethodFast() method whose code I cannot
> find.
>
> I know that the delegates invoked via Control.BeginInvoke() will use
> the window's message pump to send and retrieve the delegate and its
> arguments, so the control/form will not react to Windows messages
> while it is executing the delegate. That is the behavior I want to
> have as well when the delegate passed to
> WindowsFormsSynchronizationContext.Send() executes.
>
> For a bit of a background, I want to have this behavior in order to
> make sure that a grid control will not repaint itself while I'm re-
> populating the DataTable it is bound to. If you have other
> suggestions on how to ensure that the grid will not read from the
> DataTable at the same time a worker thread reloads it, please send
> them my way.

Well, the easiest way to block the GUI is to not run your code on the
worker thread in the first place. Just repopulate the DataTable from the
main GUI thread, and that will stop your entire GUI from working, avoiding
any chance that the user might see updates while you're changing the
DataTable.

Personally, I'm not a big fan of blocking the GUI. I don't really
understand why you don't want updates while the DataTable is being
repopulated. But why not just temporarily set the DataSource to null
while you update the DataTable and then set it back to your DataTable when
you're done? You could even put up a little "Reloading Data" TextBox over
the DataGridView control while the update happens.

Whatever your goals, I'm pretty sure you're barking up the wrong tree.
All this talk of "BeginInvoke()" and "SynchronizationContext", that stuff
isn't for blocking threads. It's for helping threads keep running. That
a method invoked using Control.Invoke() or Control.BeginInvoke() has the
ability to block the GUI thread is a side-effect and in fact one would
typically take pains to be careful about those methods to make sure they
_don't_ block the GUI thread for very long.

Pete

eugen_nw

8/14/2008 7:41:00 PM

0

Hi Peter,

Thanks for your reply. Please see some notes inline. By the way, do
you happen to know the answer to the question in the subject?

eugen

>
> Well, the easiest way to block the GUI is to not run your code on the  
> worker thread in the first place.  Just repopulate the DataTable from the  
> main GUI thread, and that will stop your entire GUI from working, avoiding  
> any chance that the user might see updates while you're changing the  
> DataTable.

[eugen] "Been there, done that". Some queries may take long to
complete and the user is left with a frozen screen that [s]he cannot
use even to activate a menu or navigate to another MDI view. The
worker threads run the queries and then merge the results in the
DataTable the controls are bound to. It is the merging of the data
only that I will execute on the UI thread.

> I don't really  
> understand why you don't want updates while the DataTable is being  
> repopulated.  

[eugen] The application crashes if a grid reads from a DataTable at
the same time the worker thread is busy clearing and repopulating it.
The grid will read the DataTable if it happens that the user sorts or
groups the grid or hits the screen's Refresh button.

> But why not just temporarily set the DataSource to null  
> while you update the DataTable and then set it back to your DataTable when  
> you're done?

[eugen] "Been there, done that" too. Some grids do not handle this
well, for example those that have grouping in effect.

Peter Duniho

8/14/2008 11:58:00 PM

0

On Thu, 14 Aug 2008 12:40:38 -0700, eugen_nw
<eugen_newsgroups@hotmail.com> wrote:

> Hi Peter,
>
> Thanks for your reply. Please see some notes inline. By the way, do
> you happen to know the answer to the question in the subject?

No, I don't. But I really don't think you need to know. If your goal is
to block the GUI until the update is done, then just run the update on the
GUI thread.

Pete