-1

最後/最新のタスクを除くすべてをキャンセルするにはどうすればよいですか?たとえば、ボタンのクリックでトリガーされる時間のかかるタスクがあるとします。最後のボタンクリックからのタスクを実行し、前のタスクをキャンセルしたいだけです。これが通常どのように行われるかを教えていただけますか?

私の試みは、すべてのタスクをキャンセルトークンとともにリストに保存し、タスクが完了するかキャンセルされたときにそれらを削除することです。TaskとCancellationTokenの両方を保存するリストを作成することは、一般的な要件であると私が考えていたものに対してやりすぎのようです(たとえば、ユーザーが何かを検索し、検索ボタンを複数回クリックする。最後の検索が行われ、他のすべてがキャンセルされましたか?)これは一般的なシナリオなので、これが通常どのように行われるかを知りたいと思います。ここでのベストプラクティスは何ですか?

async void DoStuffAsync()
{
    // Store tasks in a list
    if (tasksAndCancelTokens == null)
        tasksAndCancelTokens = new List<Tuple<Task, CancellationTokenSource>>();
    else // we have a new Get request so cancel any previous
        tasksAndCancelTokens.ForEach(t => t.Item2.Cancel());

    // Create Cancellation Token
    var cts = new CancellationTokenSource();

    // Method to run asynchonously
    Func<int> taskAction = () =>
    {
        // Something time consuming
        Thread.Sleep(5000);
        if (cts.Token.IsCancellationRequested)
           cts.Token.ThrowIfCancellationRequested();
        return 100;
    };

    // Create Task
    Task<int> task = Task<int>.Factory.StartNew(taskAction, cts.Token);
    // Create Tuple to store task in list
    var tup = new Tuple<Task, CancellationTokenSource>(task, cts);
    tasksAndCancelTokens.Add(tup);

    try
    {
        int i = await task;
    }
    catch (OperationCanceledException)
    {
        // Don't need to do anything
    }
    finally
    {
        tasksAndCancelTokens.Remove(tup);
    }
}

ありがとう

4

1 に答える 1

2

最後のタスクをキャンセルしたいだけの場合は、次のようにするだけです。

CancellationTokenSource cts = null;
async void Button1_Click(...)
{
  // Cancel the last task, if any.
  if (cts != null)
    cts.Cancel();

  // Create Cancellation Token for this task.
  cts = new CancellationTokenSource();
  var token = cts.Token;

  // Method to run asynchonously
  Func<int> taskAction = () =>
  {
    // Something time consuming
    Thread.Sleep(5000);
    token.ThrowIfCancellationRequested();
    return 100;
  };

  try
  {
    int i = await Task.Run(taskAction);
  }
  catch (OperationCanceledException)
  {
    // Don't need to do anything
    return;
  }
}
于 2013-01-24T17:06:06.557 に答える