Reputation: 709
In my WPF application, I have a long running process which converts files to PDFs using BlueBeam Q Server. When the process takes place, it should not freeze, so the below code has written to take care of that:
private void btn_convert_Click(object sender, RoutedEventArgs e)
{
thread = new Thread(new ThreadStart(WorkerMethod));
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Name = "PDF";
thread.Start();
}
WorkerMethod()
{
//code to connect to Q server and conversion goes here
}
Now, when the process starts, a cancel button will be visible to the user. When the user presses cancel, I want to abort the thread started. I wrote the code as below:
private void btn_cancel_Click(object sender, RoutedEventArgs e)
{
if (thread.Name == "PDF")
thread.Abort();
}
But the thread doesn't abort and continues the process. Please give me your valuable suggestions.
Upvotes: 1
Views: 2996
Reputation: 1004
You could use the CancellationTokenSource as described here:
http://msdn.microsoft.com/en-us/library/dd997364.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
static void CancelWithThreadPoolMiniSnippet()
{
//Thread 1: The Requestor
// Create the token source.
CancellationTokenSource cts = new CancellationTokenSource();
// Pass the token to the cancelable operation.
ThreadPool.QueueUserWorkItem(new WaitCallback(DoSomeWork), cts.Token);
// Request cancellation by setting a flag on the token.
cts.Cancel();
}
//Thread 2:The Listener
static void DoSomeWork(object obj)
{
CancellationToken token = (CancellationToken)obj;
for (int i = 0; i < 100000; i++)
{
// Simulating work.
Thread.SpinWait(5000000);
if (token.IsCancellationRequested)
{
// Perform cleanup if necessary.
//...
// Terminate the operation.
break;
}
}
}
This post describes other possible ways:
Question about terminating a thread cleanly in .NET
Upvotes: 1
Reputation: 56697
You should avoid Abort
whenever possible. Search SO for how to cancel threads gracefully - which can not be done when the thread code calls other code you can not influence, like a third party library method or something like that.
For example if your thread method does something like this:
WorkerMethod()
{
CallFunctionInExternalDLL();
}
it can not be aborted properly.
To "cancel" such a thread, it's best to indicate to the thread it should cancel (using a bool
flag, for example) and have the thread roll back its result (for example, delete a created PDF or things like that). Your application could then just continue as if the thread had never been started.
For example your code could then look like this:
WorkerMethod()
{
CallFunctionInExternalDLL();
if (m_threadAborted)
RollBackWhatFunctionDid();
}
If your thread looks like this:
WorkerMethod()
{
while (true)
{
CallFunctionInExternalDLL();
}
}
You could do this:
WorkerMethod()
{
while (!m_threadAborted)
{
CallFunctionInExternalDLL();
}
if (m_threadAborted)
RollBackStuff();
}
In these examples, m_threadAborted
is a bool
flag declared like this:
private volatile bool m_threadAborted = false;
Upvotes: 4
Reputation: 4104
You can use Backgroundworker instead of Thread, and you will be able to cancel it if you code include a loop (you have to test a Boolean property in each loop)
// define the backgroundWorker
this.backgroundWorker.DoWork += new DoWorkEventHandler(this.BackgroundWorker_DoWork);
this.backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BackgroundWorker_RunWorkerCompleted);
this.backgroundWorker.WorkerSupportsCancellation = true;
// execute process
this.backgroundWorker.RunWorkerAsync();
// cancel process
this.backgroundWorker.CancelAsync();
and in your code of BackgroundWorker_DoWork :
// in a loop
if (this.backgroundWorker.CancellationPending == false)
{
...
}
Upvotes: 1