-3

I am using an asynchronous method. How can I stop its execution when a Timer raises a timeout event?

My code:

public async Task<object> Method()
{
    cts = new CancellationTokenSource();
    try
    {
        timer = new System.Timers.Timer(3000);
        timer.Start();
        timer.Elapsed += (sender, e) =>
        {
            try
            {
                timer_Elapsed(sender, e, cts.Token, thread);
            }
            catch (OperationCanceledException)
            {
                return;
            }
            catch (Exception ex)
            {
                return;
            }
        };
        await methodAsync(cts.Token);
        return "message";
    }
    catch (OperationCanceledException)
    {
        return "cancelled";
    }
    catch (Exception ex)
    {
        return ex.Message;
    }
}

// Async Call
public async Task<object> methodAsync(CancellationToken ct)
{
    try
    {
        pdfDocument = htmlConverter.Convert("path", "");
    }
    catch(Exception ex)
    {
        return x.Message;
    }
}

// Timer event
void timer_Elapsed(object sender, ElapsedEventArgs e, CancellationToken ct)
{ 
    cts.Cancel();
    ct.ThrowIfCancellationRequested();
}
Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
Gokul Kumar
  • 389
  • 6
  • 16
  • 2
    You seem to be trying to cancel the code `htmlConverter.Convert("path", "")`. There's no way to cancel this code as code that cancels must be able to respond to the cancellation token. So the only answer is that you need to spin up a new process and kill that if you need to cancel. Otherwise the only safe action is let this code run to completion. – Enigmativity Feb 04 '17 at 06:58
  • I am not trying to cancel this `pdfDocument = htmlConverter.Convert("path", "");` code. Just try to kill the methodAsync() function. Is there any way? – Gokul Kumar Feb 04 '17 at 10:49
  • The only thing going on in the `methodAsync` function is the call to `.Convert` so stopping one is the same as stopping the other. You cannot safely force the task/thread to cancel. You have to be able to respond to the cancellation token for it to work. – Enigmativity Feb 04 '17 at 23:40
  • Thanks for your update – Gokul Kumar Feb 06 '17 at 09:29
  • Did the answer I posted help you? – Enigmativity Feb 06 '17 at 09:57

2 Answers2

1

Here's how canceling a task works:

public async Task<object> Method()
{
    cts = new CancellationTokenSource();
    await methodAsync(cts.Token);
    return "message";
}

public Task<object> methodAsync(CancellationToken ct)
{
    for (var i = 0; i < 1000000; i++)
    {
        if (ct.IsCancellationRequested)
        {
            break;
        }
        //Do a small part of the overall task based on `i`
    }
    return result;
}

You have to respond to the change in the property of ct.IsCancellationRequested to know when to cancel the task. There is no safe way for one thread/task to cancel another thread/task.

In your case it appears that you are trying to call a single method that doesn't know about the CancellationToken so you can not cancel this task safely. You must let the thread/task continue to completion.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
0

I think you can try mentioning when to cancel it. Something like

cts.CancelAfter(TimeSpan.FromMilliseconds(5000));

Also, you need to use the cancellation token in the called methods. That's when you will know when to cancel.

Teja
  • 305
  • 1
  • 6