BackgroundWorker - C#
I am developing a multithreading application using BackroundWorker. In the Do_Work method I call a开发者_JAVA技巧nother method, in that method I add a lot of data into a list using a while-statement. My goal is to add all the data that in the list to show in a GridView. How can I do that so every time data adds to the list, the gridview uppdates? Instead of waiting until that the while-statement has finished running. When the while-statment adds a value to the list, the value inserts into the gridview?
It must be in the ProgressChanged, but I dont know how to do that.
Add a progress changed event handler to your worker
In your Do_Work method
BackgroundWorker worker = sender as BackgroundWorker;
worker.ReportProgress(0, new DataObject())
In your progess handler
DataObject data (DataObject)e.UserState;
yourList.Add(data);
If you know how far you are along you can send the actual done count in ReportProgess instead of 0.
My method was to create a class that would hold any data that I am passing back and forth. When you call ReportProgress
it will require the percentage increment and an object argument. You put your class into this object argument, and from the ProgressChanged
event this object is made available through the ProgressChangedEventArgs
. You can then read this data, input it into the control you are wanting to update and then call the Refresh()
method on that control to update it in the UI without freezing the interface.
http://msdn.microsoft.com/en-us/library/a3zbdb1t.aspx
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.progresschanged.aspx
Edit: (psuedocode, untested)
private List<Customer> _customerList = new List<Customer>();
protected void DoWork(object sender, DoWorkEventArgs e)
{
MyDataGridView.DataSource = _customerList; // Here is where you'll set your data source and bindings
Load_Customer_Method();
}
private void Load_Customer_Method()
{
int totalCustomers = 20;
int currentCustomer = 1;
for(currentCustomer = 1; currentCustomer <= totalCustomers; currentCustomer++)
{
Customer c = new Customer();
// Configure customer
ReportProgress(100*currentCustomer/totalCustomers, c);
}
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Customer addedCustomer = (Customer)e.UserState;
_customerList.Add(addedCustomer); // If bindings are set, this update is automatic
MyDataGridView.Refresh(); // Force a refresh of the screen for this grid to make
// it appear as if the grid is populating one object at
// a time.
}
This might help. I have a class called WorkerThread that does the work we want
static void Main( string[] args )
{
// create the background worker object
BackgroundWorker _worker = new BackgroundWorker();
// tell the background worker it can be cancelled and report progress
_worker.WorkerReportsProgress = true;
_worker.WorkerSupportsCancellation = true;
// a worker thread object where the actual work happens
WorkerThread thread = new WorkerThread();
// add our event handlers
_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler( thread.RunWorkerCompleted );
_worker.ProgressChanged += new ProgressChangedEventHandler( thread.ProgressChanged );
_worker.DoWork += new DoWorkEventHandler( thread.DoWork );
// start the worker thread
_worker.RunWorkerAsync();
// wait for it to be completed
while( !_worker.CancellationPending )
{
// sleep for a second
Thread.Sleep( 1000 );
}
Console.ReadKey();
}
Now in the WorkerThread class
public class WorkerThread
{
public void DoWork( object sender, DoWorkEventArgs e )
{
//get a handle on the worker that started this request
BackgroundWorker workerSender = sender as BackgroundWorker;
// loop through 10 times and report the progress back to the sending object
for( int i = 0; i < 10; i++ )
{
// tell the worker that we want to report progress being made
workerSender.ReportProgress( i );
Thread.Sleep( 100 );
}
// cancel the thread and send back that we cancelled
workerSender.CancelAsync();
e.Cancel = true;
}
public void RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e )
{
Console.WriteLine( "Worker Done!!" );
}
public void ProgressChanged( object sender, ProgressChangedEventArgs e )
{
// print out the percent changed
Console.WriteLine( e.ProgressPercentage );
}
}
I am using a custom class, you could use a method in your class that is creating the background worker. Just modify the code in the ProgressChanged event.
I suggest you to read on the backgroundworker. You have all the info and example there :
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
All you will need to do is to pass your item as parameter in ReportProgress and in the event ProgressChanged add your item in your grid.
精彩评论