Hi John,
Make sure that you are updating the data source on the UI thread only.
If you're using the 2.0 framework use the BackgroundWorker class to run the
async process but don't load the data directly into the data source from
within the DoWork event handler. Instead, save a copy of the data and make
sure the copy is accessible to the RunWorkerCompleted event handler. The
BackgroundWorker class makes sure that the RunWorkerCompleted event handler is
invoked on the UI thread, where you can update the real data source with the
downloaded data:
private void RunProcessAsync()
{
BackgroundWorker worker = new BackgroundWorker();
string asyncData = null;
// use an anonymous method to do the async work
worker.DoWork += delegate(object sender1, DoWorkEventArgs e1)
{
asyncData = "Async Data From BackgroundWorker";
};
// use an anonymous method to process completion
worker.RunWorkerCompleted += delegate(object sender2,
RunWorkerCompletedEventArgs e2)
{
// update data source
realDataSource = asyncData;
};
worker.RunWorkerAsync();
}
If you're using an early framework version then you should call Invoke on the
Form to marshal the call to the UI thread yourself. This can be done from
within the background thread after the download operation has completed.
Again, you shouldn't update the real data source in the background thread, but
save a copy of the downloaded data and update the data source from within the
method executed by the Invoke method:
private void RunProcessAsync()
{
string asyncData = null;
ThreadPool.QueueUserWorkItem(new WaitCallback(RunProcess), asyncData);
}
private void RunProcess(object state)
{
string asyncData = (string) state;
asyncData = "Async Data From ThreadPool";
// marshal a call back to the UI thread to update the data source
Invoke(new ProcessCompleteInvoker(ProcessComplete), asyncData);
}
private delegate void ProcessCompleteInvoker(string asyncData);
private void ProcessComplete(string asyncData)
{
// update data source
realDataSource = asyncData;
}
In my examples I'm simply setting a string value to the "realDataSource"
variable, but you can perform any operation that is required by your
application, such as updating a DataTable or calling Refresh on a Binding.
If this doesn't work for you then I suspect your bindings might have been
setup incorrectly or you're not updating the appropriate data source.
--
Dave Sexton
"John J. Hughes II" <no@invalid.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
>I have a DataGridView with a TextBoxColumn. I setting the data source to a
List<stringvalue in a static class. The list is filled from a background
thread. So far all is fine and it works great, at least on my system.
The reason I am doing this is some customers are pulling from VPN
connections which are slow. This allows the list of rows in the data grid
to appear a little quicker while the list which are not used as soon load in
the background.
Oh so with a LAN connection there is no problem since everything loads too
quick to notice. But on the slower connections which I simulate with a
sleep command in the list fill the data grid's text box column comes up
empty as expected. When the list is filled the main window needs to update
the cell to display the data.
So to fill the cell I have tried a couple things.
First doing a refresh on the binding that holds the data source. This works
on drop down list but not on the data grid text boxes.
((CurrencyManager)this.BindingContext[this.ratesDataGridViewTextBoxColumn.DataSource]).Refresh();
Second replacing the data source with the same data source. This refreshes
all the displayed cell except the selected one and when you scroll up there
are still empty cell that may or may not in the course of time fill.
this.ratesDataGridViewTextBoxColumn.DataSource =
Data.clsCacheData.CacheHolder.DialingProperties;
Third attempt was doing a refresh on the data grid itself. Looks bad
(flicker) and does not update all the cells.
this.DataGridView1.Refresh().
Does anyone have another suggestion?
Regards,
John