Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/212.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 一段时间后取消异步任务_Java_Android_Android Asynctask - Fatal编程技术网

Java 一段时间后取消异步任务

Java 一段时间后取消异步任务,java,android,android-asynctask,Java,Android,Android Asynctask,这可能是一个重复的问题,但我没有找到我要找的。 我正在UI活动new LoadData().execute()中调用一个异步任务

这可能是一个重复的问题,但我没有找到我要找的。 我正在UI活动
new LoadData().execute()中调用一个异步任务
class LoadData extends AsyncTask<String, String, String>
{
    @Override
    protected void onPreExecute() {
    super.onPreExecute();
    startTime = System.currentTimeMillis();
    }
    protected String doInBackground(String... args)
    {

        DataCollector dc = new DataCollector();
        data = dc.collectData(query);
        //Here I check if the time is greater than 30 seconds then cancel
        if(((System.currentTimeMillis()-startTime)/1000)>30)
        {
           cancel(true);
        }
    return null;
    }
}
class LoadData扩展了异步任务
{
@凌驾
受保护的void onPreExecute(){
super.onPreExecute();
startTime=System.currentTimeMillis();
}
受保护的字符串doInBackground(字符串…args)
{
DataCollector dc=新的DataCollector();
数据=dc.collectData(查询);
//这里我检查时间是否大于30秒,然后取消
如果(((System.currentTimeMillis()-startTime)/1000)大于30)
{
取消(真);
}
返回null;
}
}
但这并不能在30秒后停止任务,事实上这需要更多的时间。 我尝试了
get(长超时,时间单位),但这也不起作用

有人能告诉我怎么做吗?或者我如何在doInBackground中使用isCancelled()


谢谢。

您必须在不同的线程上执行时间检查

您当前要做的是:执行
dc.collectData(查询)
(在后台)并在准备好后检查是否应该取消。因此,如果查询需要1分钟,您将在1分钟后执行取消检查,这已经太晚了

您可以做的是安排一个TimerTask,它应该在LoadData().execute()之后运行30秒,如果计时器任务已运行,您可以取消异步任务(如果它仍在运行)

尝试以下操作:

public class MyTask extends AsyncTask<Void, Void, Void> {

    private volatile boolean running = true;
    private final ProgressDialog progressDialog;

    public MyTask(Context ctx) {
        progressDialog = gimmeOne(ctx);

        progressDialog.setCancelable(true);
        progressDialog.setOnCancelListener(new OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                // actually could set running = false; right here, but I'll
                // stick to contract.
                cancel(true);
            }
        });

    }

    @Override
    protected void onPreExecute() {
        progressDialog.show();
    }

    @Override
    protected void onCancelled() {
        running = false;
    }

    @Override
    protected Void doInBackground(Void... params) {

        while (running) {
            // does the hard work
        }
        return null;
    }

    // ...

}
公共类MyTask扩展了AsyncTask{
private volatile boolean running=true;
私人最终进度对话;
公共MyTask(上下文ctx){
progressDialog=gimmeOne(ctx);
progressDialog.setCancelable(真);
progressDialog.setOnCancelListener(新的OnCancelListener(){
@凌驾
public void onCancel(对话框接口对话框){
//实际上可以设置running=false;就在这里,但我会
//坚持合同。
取消(真);
}
});
}
@凌驾
受保护的void onPreExecute(){
progressDialog.show();
}
@凌驾
受保护的void onCancelled(){
运行=错误;
}
@凌驾
受保护的Void doInBackground(Void…参数){
(跑步时){
//这项工作很辛苦吗
}
返回null;
}
// ...
}

有关更多详细信息,请参阅此答案。

简短的答案是,异步任务一旦启动,您就不能取消它。您可以做的是在
doInBackGround()
中插入一个循环,该循环将检查
isCancelled()
,如果它在将来某个时候被设置为true,则从函数返回一个值(如果您已经定义了它,它将依次调用
onPostExecute()


请注意,不能停止异步任务并不意味着操作系统在内存不足时不会取消它。如果您在AsyncTask中执行基本任务(您希望100%执行的任务),您应该记住这一点。如果是这样的话,最好使用一个-a组件,该组件会根据需要由操作系统自动终止并重新启动。

您需要一个线程,该线程会在一段时间后取消任务。该线程可能如下所示:

public class TaskCanceler implements Runnable{
    private AsyncTask task;

    public TaskCanceler(AsyncTask task) {
        this.task = task;
    }

     @Override
     public void run() {
        if (task.getStatus() == AsyncTask.Status.RUNNING )
            task.cancel(true);
     }
}
protected async Task<String> doInBackgroundAsync(String... args)
{
    DataCollector dc = new DataCollector();
    int timeout = 1000;
    var task = dc.collectDataAsync(query);
    if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
        // task completed within timeout
        data = task.Result;
    } else { 
        // timeout logic
    }
}
当调用AsyncTask时,需要在一定时间后运行cancle任务(=超时,在本例中为20秒)

这是一个好主意,如果你清理这个取消或结束与

if(taskCanceler != null && handler != null) {
     handler.removeCallbacks(taskCanceler);
}

当然,您可以将其包装到AsyncTask的自定义实现中。我已经用过很多次了,它就像一个符咒。需要注意的一点是,在极少数情况下,处理程序不会启动,我怀疑如果在错误的上下文中创建它,它在某些情况下将无法生存,因此我强制处理程序成为UI线程,并使用
handler=new handler(Looper.getMainLooper())

我将把这转化为一个异步/等待问题,使所有昂贵的方法都成为异步方法

首先,将DataCollector的collectData(查询)修改为collectDataAsync(查询)。(如果您不能修改DataCollector,那么可以使用lambda函数或类似的方法来包装它)

其次,将doInBackground更改为异步任务,如下所示:

public class TaskCanceler implements Runnable{
    private AsyncTask task;

    public TaskCanceler(AsyncTask task) {
        this.task = task;
    }

     @Override
     public void run() {
        if (task.getStatus() == AsyncTask.Status.RUNNING )
            task.cancel(true);
     }
}
protected async Task<String> doInBackgroundAsync(String... args)
{
    DataCollector dc = new DataCollector();
    int timeout = 1000;
    var task = dc.collectDataAsync(query);
    if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
        // task completed within timeout
        data = task.Result;
    } else { 
        // timeout logic
    }
}
受保护的异步任务doInBackgroundAsync(字符串…args)
{
DataCollector dc=新的DataCollector();
int超时=1000;
var task=dc.collectDataAsync(查询);
if(wait Task.wheny(Task,Task.Delay(timeout))==Task){
//任务在超时时间内完成
数据=任务。结果;
}否则{
//超时逻辑
}
}
基本上,doInBackgroundAsync中有两个任务:collectDataAsync和一个延迟任务。 您的代码等待更快的代码。然后你知道是哪一个,你可以做出相应的反应

如果还需要取消collectDataAsync任务,则需要使用cancellationToken。 我用这个来解决你的问题

注意,现在doInBackgroundAsync是一个异步的,所以它稍微改变了使用它的方式


希望有帮助。

这是正确的,但它允许用户始终取消作业,并且在30秒后不会自动取消作业。您可以在后台使用计时器,设置一些时间,例如30秒,然后在发布取消()之后…它将随时停止您的异步任务point@Shruti:谢谢您的参考,但我不想允许用户取消操作。而且
cancel(true)
似乎对我不起作用。如何使用
get(长超时,时间单位)因为这听起来更可行。事实上,有时由于连接问题或传感器脱机,我通过套接字连接从外部传感器收集数据,这个过程可能需要很长时间