如何取消Service/IntentService/AsyncTask/Looper

发布于 2024-12-03 10:22:25 字数 723 浏览 1 评论 0原文

我在这里要疯了。 我想要一件简单的事情 - 我有一个很长的任务(从网络上获取多个数据对象)并且我希望能够取消它。 我尝试了很多东西(很多)但没有任何效果

流程是这样的:

  1. 用户单击按钮

  2. 我开始工作(我尝试使用< code>AsyncTask、ServiceIntentServiceLooper

  3. 该任务负责处理所有事务,包括添加进度更新的持续通知

  4. 通知中的意图调用了一个新活动,她的唯一目的是取消正在进行的任务

  5. 我尝试调用的cancelActivity中

    stopService() 对于 Service/IntentService 或执行 Looper.quit() for Looper (我不记得我为 AsyncTask 尝试了什么,不确定是否有这样的 api 来取消它)

在我看来,最好的选择是使用 < code>IntentService (我可以排列多个任务,IntetService 会按照我想要的顺序执行)但是 我愿意接受任何类型的实现建议 - 我不在乎代码是什么,只是我可以选择取消任务

提前感谢您的帮助

Dror

(我要去睡觉了 -在同一个问题上花费 8 个小时实在是太多了)

I'm going nuts here.
I want a simple thing - I have a long task (fetching several data objects from the web) and I want the ability to cancel it.
I tried a lot of things (a lot) and nothing works

The flow goes like this:

  1. the user click on a button

  2. I start the work (I tried with AsyncTask, Service, IntentService and Looper)

  3. the task takes care of everything including adding ongoing notification for progress updates

  4. the intent in the notification has a call for a new activity that her only purpose is to cancel the ongoing task

  5. in the cancelActivity I tried to call stopService() for Service/IntentService or do
    Looper.quit() for the Looper (I don't remember what I tried for AsyncTask, not sure if there is such api for canceling it)

In my point of view the best option will be using IntentService (I could have several task lining up and IntetService will do it in order like I want) but
I'm open to suggestions for any type of implementation - I don't care what the code will be, just that I will have the option to cancel the task

Thank you in advance for your help

Dror

(I'm off to bed - 8 hours on the same issue is just too much)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧伤还要旧人安 2024-12-10 10:22:25

如果您无法识别后台逻辑中的停止条件,那么使用什么特定操作来停止任务并不重要。彻底实现这一目标的唯一方法是后台工作人员善意地停止并退出。

您可以使用几种可能的场景和解决方案来取消后台工作。

  • 后台线程执行许多短步骤(例如使用一些循环进行计算)。在这种情况下,请检查操作之间的某个标志(可以是 isInterrupted()),如果该标志指示操作必须停止,则退出。
  • 后台线程正在等待监视器。在后台线程上调用 interrupt(),在异常处理程序中捕获异常,并采取适当的步骤干净地完成此任务并退出。
  • 后台线程正在等待 IO。在一般情况下,这个用例很难解决。如果您使用某些套接字,您可以尝试从外部关闭该套接字并捕获异常。在最坏的情况下,您可以放弃线程,如果它从 IO 返回,它就知道它已被取消,并且 IO 结果必须被丢弃。如果你经常这样做 - 你会耗尽内存,所以我不会真正推荐它。

无论如何,如果任务不知道被停止的可能性,就没有办法停止你的任务(除了杀死非常糟糕的线程)。

It does not matter what specific operation you use to stop the task if you don't recognize the stop condition in your background logic. The only way to cleanly accomplish it is if background worker stops and exits in good faith.

There are few possible scenarios and solutions that you can use for canceling background work.

  • Background thread executes many short steps (for example computation with some loops). In this case, check some flag (could be isInterrupted()) between operations and exit if this flag indicates that operation must stop.
  • Background thread is waiting on monitor. Call interrupt() on background thread, catch exception in in exception handler make appropriate steps to finish this task cleanly and exit.
  • Background thread is waiting on IO. This use case is very hard to solve in general case. If you use some socket, you can try closing this socket externally and catch the exception. In worst case scenario, you can just abandon the thread in the state that if it ever returns from IO it knows that it is canceled and IO results must be discarded. If you do it often - you will run out of memory, so I would not really recommend it.

In any case, there is no way (except killing the thread which is really bad) to stop your task if it does not know about possibility of being stopped.

奢望 2024-12-10 10:22:25

好吧,我设法做了一些接近我想要的事情。

我正在使用 IntentService 来对我的任务进行排队。每个新任务都是AsyncTask。 AsyncTask 首先发送带有用于 cancelActivity 的未决意图的通知。

单击通知时,用户会收到有关停止任务的警告弹出窗口。如果他点击“是”,我就会在 IntentService 上执行 stopService() 操作。

在 IntentService 中我添加了:

    @Override
public void onDestroy() {
    currentTask.cancel(true);
    if (mNotificationHelper != null)
        mNotificationHelper.completed();
    super.onDestroy();
    stopSelf();
}

在 AsyncTask 中我添加了:

    @Override
protected void onCancelled() {
    isCanclled = true;
    httpClient.getConnectionManager().shutdown();
    mNotificationHelper.completed();
    if (mAsyncTaskListener != null)
        mAsyncTaskListener.AsyncTaskCanceled();
}

这样就会删除当前正在运行的所有连接。在执行工作的实际代码中,我需要捕获连接关闭的异常并处理它,

所以最后我实际上并没有停止 AsyncTask/Service ,而是公开 httpClient 所以我将为什么能够异步断开连接。

我觉得有点难看,但我没有其他办法,

谢谢大家

Ok, i manged to do something close to what I want.

I'm using IntentService that will queue my task. each new task is AsyncTask. the AsyncTask starts with sending notification with pendingIntent for cancelActivity.

When clicking on the notification the user gets a warning popup about stopping the task. If he clicks yes than I do stopService() on my IntentService.

In the IntentService I added:

    @Override
public void onDestroy() {
    currentTask.cancel(true);
    if (mNotificationHelper != null)
        mNotificationHelper.completed();
    super.onDestroy();
    stopSelf();
}

in the AsyncTask I added:

    @Override
protected void onCancelled() {
    isCanclled = true;
    httpClient.getConnectionManager().shutdown();
    mNotificationHelper.completed();
    if (mAsyncTaskListener != null)
        mAsyncTaskListener.AsyncTaskCanceled();
}

so that will drop all the connection currently in motion. In the actual code that do the work I need to catch the exception for connection shutdown and handle it

so in the end I'm not actually stopping the AsyncTask/Service but rather exposing the httpClient so I will be able to drop the connection in asynchrony why.

I think is a bit ugly but I got no other way

thank you all

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文