Cancel a thread that is executing a long request

I have a thread that calls one of the methods, now this method executes a request, which can take a very long time, maybe about 40 minutes to complete,

I want to give the user the ability to cancel this operation (which means stopping the stream and stopping the request to release the database).

I should mention that I am developing a WPF application using .net 4.5, SQL SERVER DB and C #.

+5
source share
5 answers

You have to use backgroundworker , this is exactly what you want.

Drag it from the toolbar or create in code. It supports cancellation, reports on progress made, notifies completion and knows whether it works or not.

Here is an example.

void method(){ BackgroundWorker worker = new BackgroundWorker(); worker.RunWorkerCompleted += worker_RunWorkerCompleted; worker.ProgressChanged += worker_ProgressChanged; worker.DoWork += worker_DoWork; worker.WorkerSupportsCancellation = true; if(!worker.IsBusy) { worker.RunWorkerAsync(); } } void worker_DoWork(object sender, DoWorkEventArgs e) { //do whatever needs to be done on the other thread here. object argument = e.Argument; //if passed argument in RunWorkerAsync(). object result = new object(); e.Result = result; //after making worker global, you can report progress like so: worker.ReportProgress(50); //you can also pass a userState, which can be any object, to show some data already. } void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) { //you can update a progress bar in here int progress = e.ProgressPercentage; } void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { //when done } void CancelTheTask() { if (worker.IsBusy) { //make worker global first, but then worker.CancelAsync(); } } 

Important things to note: never use resources in the DoWork method that are not created inside it. So pass what you need in the background worker as โ€œArgumentsโ€. And the things created by the creator of backgroundwork should not be set to the global ether variable, pass the result.

When canceled, RunWorkCompleted will also be launched. Now the database query is already running, so it still works, even when your application has lost all the resources for it.

To undo this, we will need to find out how you are executing the request, for example, @ S. Akbari is one way. Entity Framework 6 also supports cancellation.

To do this: check this when using Queryable

here is another example

Or this solution without Entity Framework.

+4
source
+2
source

When your thread is blocked while waiting for a request, it is useless to stop something.

Make sure the SqlConnection request is accessible from your user interface and close it. Drop the Thread, it will end (with an error that you must suppress).

+2
source

If a UI thread performs a lengthy operation, it will not be able to process UI Requests. This is also called Not Responding . Use ThreadPool as follows:

 CancellationTokenSource ct;//instantiate it before ThreadPool.QueueUserWorkItem line private void operation_Click(object sender, RoutedEventArgs e) { ct = new CancellationTokenSource(); ThreadPool.QueueUserWorkItem(_ => { var result = LongTimeOperation();//set the operation in another thread so that the UI thread is kept responding //use the Dispatcher to "return" to the UI thread Dispatcher.BeginInvoke(new Action(() => { //Use result for example : Label1.Text = result.ToString(); })); }); } 

To enable the user to cancel the operation, use the CancellationTokenSource as follows:

 private void cancel_Click(object sender, RoutedEventArgs e) { if (ct != null) { ct.Cancel(); ct= null; } } 

Note: in LongTimeOperation () you must have another parameter of type CancellationToken

 private float LongTimeOperation(CancellationToken ct) { if (ct.IsCancellationRequested) return -1; .... .... } 

This link is useful for Cancellation in managed threads.

+1
source

This is a common problem. But in WPF and WinForm I would like to use BackGroundWorker . See here

-1
source

All Articles