如何在不再需要时删除Dart future

时间:2015-02-20 15:04:37

标签: dart dart-async

这与is there any way to cancel a dart Future?

有关

就我而言,没有HTTP,只是昂贵的计算。我有一个表格/列表,我滚动浏览。随着元素变得可见,我生成期货以显示计算结果。但是如果我(最终用户)快速滚动,一些结果将会#"滚出视图"并且将不再需要。这可能是一个很大的数字,并将严重延迟在当前可见元素中显示的有用的期货(结果)的返回:-)。可以做些什么呢?老板,史蒂夫

1 个答案:

答案 0 :(得分:2)

您可以设置一个标志,指示延迟代码(从期货运行)不再需要结果。 当调用延迟代码时,它只会返回。

library cancel_future;

import 'dart:async' show Future, Timer;
import 'dart:math' show Random;

typedef void TaskFunction(Task task);

// Container for a task
class Task {
  // an assigned task id
  final id;
  // data to process
  int data;
  // Indicate to the task function, that it should stop processing
  bool isCanceled = false;
  // The task function must set this flat to true when all work is done.
  bool isFinished = false;
  // The task function which processed the data and sets the result.
  TaskFunction fn;
  // The result set by the task function when it finished processing.
  int result;

  Task(this.id, this.data, this.fn);

  // Start processing the task.
  void execute() => fn(this);
}

final rnd = new Random();

void main(List<String> args) {

  // create tasks
  final tasks = new List<Task>.from(generate());

  // start all tasks
  tasks.forEach((t) => t.execute());

  // after random delay cancel all unfinished tasks
  new Future.delayed(new Duration(seconds: rnd.nextInt(10)), () {
    tasks.forEach((t) {
      if (!t.isFinished) {
        t.isCanceled = true;
      }
    });
  }).then((_) {
    // check results
    int done = 0;
    int canceled = 0;
    tasks.forEach((t) {
      print(
          'Task id: ${t.id}; isCanceled: ${t.isCanceled}; isFinished: ${t.isFinished}; data: ${t.data}; result: ${t.result}');
      if (t.isFinished) {
        done++;
      }
      if (t.isCanceled) {
        canceled++;
      }
    });

    print('Canceled: $canceled.');
    print('Done: $done.');
  });
}

// geneator for job 100 jobs
Iterable<Task> generate() sync* {
  int i = 0;

  while (i++ < 100) {
    yield new Task(i, rnd.nextInt(100), calc);
  }
}

// job function
void calc(Task t) {
  // do a bit of work every 100ms to simulate longer processing
  new Timer.periodic(new Duration(milliseconds: 100), (timer) {
    var result = 0;
    // check if jost was canceled and stop processing in case it was.
    if (t.isCanceled) {
      timer.cancel();
      return;
    }
    // while not finished do a chunk of work
    if (result < t.data) {
      result++;
    } else {
      // finished - clean up and store result
      t.isFinished = true;
      t.result = result;
      timer.cancel();
    }
  });
}