Android 中的两个并发 AsyncTasks - 如何处理竞争条件?



每次按下按钮和每次释放按钮时,我都会发送HTTP帖子。在释放按钮之前,我可能不会收到"按下的"开机自检的响应,因此我尝试同时运行这些任务。但是,有时,释放按钮的 POST 请求会在请求按下按钮之前发送到服务器。如何避免/解决此问题?

button = (ImageButton) findViewById((R.id.button1));
button.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
HTTPAsyncTask task = new HTTPAsyncTask();
if (event.getAction() == MotionEvent.ACTION_DOWN ) {
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Utilities.StringCollection.rotateRight);
return true;
}
else if (event.getAction() == MotionEvent.ACTION_UP){
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Utilities.StringCollection.stop);
return true;
}
return false;
}
});

从概念上讲,您的HTTPAsyncTaskdoInBackground()由 2 个不同的操作组成:

  1. 连接,并将请求排队到套接字
  2. 接收响应

(之后,当然,onPostExecute()将被调用。

如前所述,您需要在两个不同的线程上控制操作 #1 的执行顺序,同时允许操作 #2 并行发生。

使用通用AsyncTask机制无法做到这一点,因为您没有提供任何"将任务一分为二"的方法;线程 A 无法确定线程 B 何时从操作 #1 切换到操作 #2,反之亦然。

可以添加这样的逻辑,但您尚未解释如何进行套接字调用。

然而,提供额外的细节没有什么意义;与网络请求相关的边缘情况会破坏您可能拥有的任何订单保证。网络是有损的;请求可能会失败,响应可能会失败。即使请求是按顺序发送的,请求也可能无序到达(尤其是在使用两个单独的套接字时(。自动重试可能需要几秒钟才能完成。

IOW,"按下"的请求可能会被网络丢失,您可能需要在"未按下"请求完成后的某个时间将其重新排队到套接字。

我建议您放弃正在寻求的"部分条件并发",只需确保在执行第二个HTTPAsyncTask之前已完成第一个。

或者,您可以为每个 POST 添加一个顺序的"请求 ID",或者在第二个请求中包含有关第一个请求的信息,以便服务器能够整理出所发生的情况,即使请求无序到达也是如此。

如果你的最小 SDK 是 11 "HONEYCOMB",你可以像这样调用 asyncTask 在单个线程中运行它,以防止它们之间的竞争情况:

button = (ImageButton) findViewById((R.id.button1));
button.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
HTTPAsyncTask task = new HTTPAsyncTask();
if (event.getAction() == MotionEvent.ACTION_DOWN ) {
task.execute(Utilities.StringCollection.rotateRight);// using one thread
return true;
}
else if (event.getAction() == MotionEvent.ACTION_UP){
task.execute(Utilities.StringCollection.stop);// using one thread
return true;
}
return false;
}
});

重要说明:网络 I/O 不可靠,网络包可能会丢失或无法按发送顺序接收,但我在标题中看到了这个问题

"Android 中的两个并发 AsyncTasks - 如何处理竞争条件? ">

刚刚回答了这个问题。因此,您无法确定以这种方式接一个地收到一个请求。我建议您在一个请求中向服务器发送两个事件,并在服务器中对其进行分析。

最新更新