AsyncTask を起動するボタン アクションがあるとします。ボタンを10回クリックするとどうなりますか?タスクは 10 回実行され、バックグラウンドで実行されますか? または、以前のタスクがキャンセルされ、タスクが再開されましたか (それが私の望ましい動作ですか)?
public void myButtonClick(View v) {
new MyAsyncTask().execute(params);
}
AsyncTask を起動するボタン アクションがあるとします。ボタンを10回クリックするとどうなりますか?タスクは 10 回実行され、バックグラウンドで実行されますか? または、以前のタスクがキャンセルされ、タスクが再開されましたか (それが私の望ましい動作ですか)?
public void myButtonClick(View v) {
new MyAsyncTask().execute(params);
}
ボタンをクリックするたびに、 の新しいインスタンスが生成されますMyAsyncTask
。つまり、各タスクが作成され、最後まで実行されます。
以前に起動したタスクを停止したい場合は、最後に起動したタスクへの参照を保存し、次のようにキャンセルする必要があります。
public void myButtonClick(View v) {
if (this.lastMyAsyncTask != null && this.lastMyAsyncTask.getStatus() != AsyncTask.Status.FINISHED){
this.lastMyAsyncTask.cancel();
}
this.lastMyAsyncTask = new MyAsyncTask();
this.lastMyAsyncTask.execute(params);
}
タスクを一度に 1 回だけ実行したい場合は、スレッド化された 1 つの ThreadPool を作成する必要があります。
private ThreadPoolExecutor executor =
new ThreadPoolExecutor(1,1, 1, TimeUnit.SECONDS,
new SynchronousQueue(), new ThreadPoolExecutor.AbortPolicy());
private Future<Void> lastSubmitted;
private ReentrantLock submissionLock = new ReentrantLock();
...
try {
submissionLock.lock();
Future<Void> future =
executor.submit(new MyAsyncTask()); // assuming this implements Callable<Void>
lastSubmitted = future;
}
catch (RejectedExecutionException e) {
lastSubmitted.cancel();
Future<Void> future =
executor.submit(new MyAsyncTask()); // assuming this implements Callable<Void>
lastSubmitted = future;
}
finally {
submissionLock.unlock();
}
上記のように実行すると、既に実行中のタスクを送信しようとすると RejectedExecutionException が発生します。その場合、最後に送信されたものをキャンセルして、新しい実行をスケジュールできます。タスクは中断可能である必要があることに注意してください (InputStream/OutputStream は中断可能ではないため注意してください。代わりに Channel オブジェクトを使用してください)。
送信試行をシリアル化するには、ロックが必要です。catch ブロックの実行中に別のスレッドがタスクを送信した場合、スレッドは依然として RejectedExecutionException を受け取る可能性がありました。