如何强制取消AsyncTask?在doInBackground中,应该将标志设置为volatile吗?

10

我想强制取消AsyncTask。我看到可以使用isCancelled(),就像此有效解决方案一样(在底层使用AtomicBoolean)。

但是我看到了一些解决方案,例如可疑解决方案1可疑解决方案2可疑解决方案3,其中引入了新标志private boolean isTaskCancelled = false;

我开始想知道-由于该标志在...

public void cancelTask(){
   isTaskCancelled = true;
}

它运行在某个线程上,并且被读取。

protected Void doInBackground( Void... ignoredParams ) {
    //Do some stuff
    if (isTaskCancelled()){
        return;
    }
}

如果运行在WorkerThread中,那么标记isTaskCancelled应该是易失性的(或者像Google的实现一样使用AtomicBoolean)。


是的,它可能应该是volatile。 - thepoosh
根据谷歌指南,AsyncTask 应该用于执行非常小的功能。它不应该运行更大的循环或更重的任务。对于这样的特性,可以使用 Handlers 和 Runnable 或后台服务。标志存在,但只会在 if 条件的开始时进行验证。任务可能会按预期立即取消,也可能不会。 - chejaras
谢谢,但是您的评论并没有回答问题。 - Marian Paździoch
你对那些解决方案持怀疑态度是完全正确的。它们都有很多问题。 - G. Blake Meike
3个回答

5
是的,应该使用volatile。否则,在线程A中对变量的写入可能由于优化(由编译器、JVM等)而不会在线程B中的读取中可见。请参见此文档

是的。doInBackground在支持Executor的线程池中的一个线程上运行。很少会从同一线程运行cancelTask。这意味着isTaskCancelled被多个线程访问,必须是“volatile”的。AsyncTask框架本身使用了AtomicBoolean - G. Blake Meike

2

试一试

初始化

  private AysncTask aysncTask;

任务调用

   aysncTask=new AysncTask();
        aysncTask.execute();

在任何地方取消任务

  if ( aysncTask != null && aysncTask.getStatus() == aysncTask.Status.RUNNING ){
        aysncTask.cancel(true);

    }

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接