可中斷取消長程工作 CancellationToken

CancellationTokenSource, CancellationToken

引言

針對某些長程工作想中斷它以重新來過或真的等不下去了。

參考文件

Cancel async tasks after a period of time (C#),
CancellationTokenSource Class

原碼紀錄

FooBiz.cs
internal class FooBiz : IDisposable
{
  /// injection
  readonly ILogger<FooBiz> _logger;
  
  /// resource
  CancellationTokenSource _cts = null;

  void IDisposable.Dispose()
  {
    _cts?.Dispose();
  }

  public FooBiz(ILogger<FooBiz> logger)
  {
    _logger = logger;
  }

  public async Task<string> CallLongtermProcessAsync()
  {
    try
    {
      _cts = new CancellationTokenSource(8000); // 八秒後 timeout。
      string result = await DoLongtermProcessAsync(_cts.Token);
      return result;
    }
    catch (OperationCanceledException ex)
    {
      /// 發生中斷: A task was canceled.
      return $"OperationCanceledException: {ex.Message}";
    }
    catch (Exception ex)
    {
      return $"Exception: {ex.Message}";
    }
  }

  public void CallStopProcess()
  {
    // 立刻送出取消訊息
    _cts?.Cancel();
  }

  async Task<string> DoLongtermProcessAsync(CancellationToken stoppingToken)
  {
    // 模擬跑很久:十五秒,如:HTTP Request等。
    await Task.Delay(15000, stoppingToken);
    return $"我出運了 at {DateTime.Now:HH:mm:ss}";
  }
}
FooPage.razor
@page "/foopage"
@inject FooBiz bizSvc

<MudButton OnClick=HandleTestCancelToken>呼叫長程工作</MudButton>
<MudButton OnClick=HandleStopProcess>中斷長程工作</MudButton>
@if (message != null)
{
  <MudAlert>
    @message
  </MudAlert>
}
	  
@code {
  string message = null;

  /// 呼叫長程工作
  async Task HandleTestCancelToken()
  {
    message = "Loading...";
    message = await bizSvc.CallLongtermProcessAsync();
  }

  /// 中斷長程工作
  void HandleStopProcess()
  {
    bizSvc.CallStopProcess();
  }
}

Last updated