How to cancel a previously called method when a new instance of that method is called

58 Views Asked by At

I have an async method Foo that gets called at various points in the execution of my code, based on events coming in. I need a way to cancel any thread/instance of this method that is running whenever a new instance is called, effectively "refreshing" the method.

I thought about having a cancellationTokenSource as a class variable. I tried the following:

public static MyClass 
{
  static CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();

  public static async Task<Object> foo()
  {
    Object out = null;
    var previousTokenSource = Interlocked.Exchange(ref _cancellationTokenSource, new CancellationTokenSource());
    CancellationToken currentToken = _cancellationTokenSource.Token;
    try
    {
      previousTokenSource?.Cancel();

      await Task.Delay(1000, currentToken);
      out = ArbitraryLogic(currentToken)
    }
    catch (TaskCanceledException ex)
    {
      return null;
    }

    return out;
  }
}

So if I have the test function:

public async void Test()
{
    var out1 = MyClass.foo();
    await Task.Delay(10);
    var out2 = MyClass.foo();

    await out1;
    await out2;
    if (out1.Result != null)
        Assert.Fail("out1.Result not null");
}

I expect out1 to be null, but currently it's not. What am I doing wrong? How would I write code that effectively stops the execution of a method when a new one is called?

1

There are 1 best solutions below

0
Marc Gravell On

You are asking whether the task is null; you should be asking whether the result is null:

var x = await out1;
var y = await out2;
Assert.IsNull(x); // fine
Assert.IsNotNull(y); // (depends on ArbitraryLogic)