1

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.

antinescience
  • 2,339
  • 23
  • 31
Sangeetha
  • 699
  • 5
  • 16
  • 37
  • 1
    could you give us the code of your WorkerMethod? What Thorsten Dittmar says is correct, but depending on how you connect to the "Q server" you might be able to simply abandon the request. – void Mar 26 '13 at 13:03

3 Answers3

4

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;
Thorsten Dittmar
  • 55,956
  • 8
  • 91
  • 139
1

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)
{
...
}
Xaruth
  • 4,034
  • 3
  • 19
  • 26
1

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

Community
  • 1
  • 1
Basti
  • 994
  • 6
  • 11