Reputation: 1380
I have a windows forms application that shows data in a grid view. The data is being automatically refreshed (fetched from a DB) from a background worker thread. So to avoid any cross thread references, in the DoWork method of the background thread, I call GridView.BeginInvoke() and pass the list of messages. But in the delegate methods, the message list is empty.
If I use GridView.invoke(), the the messageList does contain the values, but sometimes there is an exception which says "object is currently in use elsewhere" which I believe is caused due to referencing UI control on a non-UI thread.
How can I solve this problem?
public delegate void AddMessagesDelegate(List<ClientMessage> tempMessageList);
private void SearchWorkerDoWork(object sender, DoWorkEventArgs e)
{
List<ClientMessage> partList = new List<ClientMessage>();
View.GridViewtMain.Invoke(new InvokeDelegate(ClearMessagesFromGrid));
//View.GridViewtMain.BeginInvoke(new InvokeDelegate(ClearMessagesFromGrid));
partList.AddRange(Model.LoadSearchResult());
View.GridViewtMain.Invoke(new AddMessagesDelegate(AddMessagesToGrid), new object[] {partList});
//View.GridViewtMain.BeginInvoke(new AddMessagesDelegate(AddMessagesToGrid), new object[] {partList});
while (!isCancelled && (partList.Count > 0))
{
partList.Clear();
partList.AddRange(Model.LoadSearchResult());
View.GridViewtMain.Invoke(new AddMessagesDelegate(AddMessagesToGrid), new object[] {partList});
//View.GridViewtMain.BeginInvoke(new AddMessagesDelegate(AddMessagesToGrid), new object[] {partList});
}
}
private void ClearMessagesFromGrid()
{
messageDataSource.Clear();
}
private void AddMessagesToGrid(List<ClientMessage> tempMessageList)
{
View.GridViewMain.BeginDataUpdate();
foreach (ClientMessage message in tempMessageList)
{
messageDataSource.Add(message);
}
View.GridViewMain.GridControl.DataSource = messageDataSource;
View.GridViewMain.EndDataUpdate();
}
Upvotes: 0
Views: 696
Reputation: 942368
partList.Clear();
You posted the code that works instead of the code you have a problem with. I'll assume BeginInvoke instead of Invoke. The partList.Clear() method is going to empty the list, before the delegate target can use the list. You should create a new instance of the list after the BeginInvoke call. The UI thread can now work with the old list without trouble. Roughly
while (!isCancelled)
{
partList = new List<ClientMessage>();
partList.AddRange(Model.LoadSearchResult());
if (partList.Count == 0) break;
View.GridViewtMain.BeginInvoke(new AddMessagesDelegate(AddMessagesToGrid), new object[] {partList});
}
Upvotes: 2