How to update a list box by an asynchronous call?
c#, delegates
Solution
For Win Forms you'll need to use the Control's Invoke method:
Executes the specified delegate on the thread that owns the control's underlying window handle
The basic scenario is:
- Do the heavy lifting work with a BackgroundWorker to retrieve all of your items on a non UI blocking thread.
- On the BackgroundWorker.RunWorkerCompleted Event, use the Control's Invoke method to add the items to the Control (ListBox in your case).
Something along the lines of:
var bw = new BackgroundWorker();
bw.DoWork += (sender, args) => MethodToDoWork;
bw.RunWorkerCompleted += (sender, args) => MethodToUpdateControl;
bw.RunWorkerAsync();
This should get you going in the right direction.
Edit: working sample
public List<string> MyList { get; set; }
private void button1_Click( object sender, EventArgs e )
{
MyList = new List<string>();
var bw = new BackgroundWorker();
bw.DoWork += ( o, args ) => MethodToDoWork();
bw.RunWorkerCompleted += ( o, args ) => MethodToUpdateControl();
bw.RunWorkerAsync();
}
private void MethodToDoWork()
{
for( int i = 0; i < 10; i++ )
{
MyList.Add( string.Format( "item {0}", i ) );
System.Threading.Thread.Sleep( 100 );
}
}
private void MethodToUpdateControl()
{
// since the BackgroundWorker is designed to use
// the form's UI thread on the RunWorkerCompleted
// event, you should just be able to add the items
// to the list box:
listBox1.Items.AddRange( MyList.ToArray() );
// the above should not block the UI, if it does
// due to some other code, then use the ListBox's
// Invoke method:
// listBox1.Invoke( new Action( () => listBox1.Items.AddRange( MyList.ToArray() ) ) );
}
Problem
I have developed a windows forms c# application, i just want update items in a Listbox in the main form by spin offing another thread without blocking the GUI form. Since threads cannot access form entities like listbox, i thought of using delegates. Following code in the below shows how i used a delegate to do that task, but it blocks the GUI form. so i just want to convert it to an asynchronous delegate which updates list box without blocking the GUI Form delegate declaration ``` delegate void monitoringServiceDel(); ``` calling the delegate ``` new monitoringServiceDel(monitoringService).BeginInvoke(null, null); ``` delegate method implementation ``` private void monitoringService() { this.listEvents.Invoke(new MethodInvoker(delegate() { int i = 0 ; while (i<50) { listEvents.Items.Add("count :" + count++); Thread.Sleep(1000); i ++; } })); } ```