G
Guest
I have a long database search operation that I am running in a separate
thread using a BackgroundWorker component. I need to give the user the
ability to cancel the operation. However, the BackgroundWorker doesn't seem
to have enough functionalality to solve my problem.
I start the thread with:
backgroundWorker.RunWorkerAsync(SQLQueryString);
The event handler looks like this:
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Define a dataAdapter using SQLQueryString, OleDBConnection etc.
OleDataAdapter da = ... etc
......
// Fill the datatable
da.Fill(dataTable);
}
Most of the time is spent in the Fill operation. The documented approach for
canceling a long operation is to:
backgroundWorker.CancelAsync();
and in the DoWork handler, periodically check for a cancel with:
if (backgroundWorker.CancellationPending) return; // triggers WorkCompleted
My problem is that the dataAdapter Fill operation can't be interrupted. So,
I would have to modify the database query and Fill the data table
incrementally like:
for (i = 0; i < 10; ++i)
{
// run modified query, getting 10% of results
.......
// Fill 10% of the datatable
da.Fill(dataTable);
// Report progress (Optional)
backgroundWorker.ReportProgress(i * 10);
// Check for cancel
if (backgroundWorker.CancellationPending) return; // Triggers WorkComplete
}
Unfortunately, this comes with a performance hit. So, instead of the above
approach, I do the following:
1. Get the backgroundWorker thread object (= workerThread).
2. workerThread.Abort()
3. backGroundWorker.Dispose()
4. For a new query, create a new BackgroundWorker.
Note that if I skip 3 and try to launch another query using the original
backgroundWorker, I get an exception saying the backgroundGround worker is
busy, even though the thread was aborted.
This seems like a bit of a hack. Is there a better solution?
Any ideas appreciated.
thread using a BackgroundWorker component. I need to give the user the
ability to cancel the operation. However, the BackgroundWorker doesn't seem
to have enough functionalality to solve my problem.
I start the thread with:
backgroundWorker.RunWorkerAsync(SQLQueryString);
The event handler looks like this:
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Define a dataAdapter using SQLQueryString, OleDBConnection etc.
OleDataAdapter da = ... etc
......
// Fill the datatable
da.Fill(dataTable);
}
Most of the time is spent in the Fill operation. The documented approach for
canceling a long operation is to:
backgroundWorker.CancelAsync();
and in the DoWork handler, periodically check for a cancel with:
if (backgroundWorker.CancellationPending) return; // triggers WorkCompleted
My problem is that the dataAdapter Fill operation can't be interrupted. So,
I would have to modify the database query and Fill the data table
incrementally like:
for (i = 0; i < 10; ++i)
{
// run modified query, getting 10% of results
.......
// Fill 10% of the datatable
da.Fill(dataTable);
// Report progress (Optional)
backgroundWorker.ReportProgress(i * 10);
// Check for cancel
if (backgroundWorker.CancellationPending) return; // Triggers WorkComplete
}
Unfortunately, this comes with a performance hit. So, instead of the above
approach, I do the following:
1. Get the backgroundWorker thread object (= workerThread).
2. workerThread.Abort()
3. backGroundWorker.Dispose()
4. For a new query, create a new BackgroundWorker.
Note that if I skip 3 and try to launch another query using the original
backgroundWorker, I get an exception saying the backgroundGround worker is
busy, even though the thread was aborted.
This seems like a bit of a hack. Is there a better solution?
Any ideas appreciated.