[英]Best way to guarantee a callback is always executed asynchronously?
I'm working an Android app that has to make server request and then perform actions when the request is completed. 我正在使用一个Android应用程序,该应用程序必须发出服务器请求,然后在请求完成时执行操作。 Here's some pseudo code to help explain the situation:
这是一些伪代码来帮助解释这种情况:
makeRequest(new SomeTask{
onDone() {
// Do actionB with queue
}
});
// Do actionA with queue. Must be execute first!!
Here's the implementation of makeRequest
in pseudo code: 这是伪代码中的
makeRequest
的实现:
makeRequest(SomeTask task) {
if(canDoOptimization) { // if true, don't need to make request
// It's a bad idea to execute this immediately.
// Wish I could wait until the current thread of execution was done...
task.onDone();
return;
}
asyncTask = new AsyncTask<SomeTask, Void, Void>() {
doInBackground(SomeTask... task) {
// Make server request...
task.onDone();
}
}
asyncTask.execute(task);
}
Usually actionA
happens before actionB
as expected, but in cases where we can avoid a network requests, SomeTask.execute
is called immediately. 通常,
actionA
会按预期在actionB
之前发生,但是在可以避免网络请求的情况下,会立即调用SomeTask.execute
。 This causes actionB
to occur before actionA
, which is bad. 这导致
actionB
在 actionA
之前 actionA
,这是不好的。 Is there any way I can guarantee this doesn't happen? 有什么办法可以保证不会发生这种情况吗?
I've run into this situation several times in javascript. 我在javascript中多次遇到这种情况。 In those cases, I would wrap the
SomeTask.execute
call with a setTimeout
or setImmediate
to maintain the proper async semantics. 在这些情况下,我将使用
setTimeout
或setImmediate
包装SomeTask.execute
调用以维护适当的异步语义。
For clarity, here's an example of the same bug in JavaScript: https://gist.github.com/xavi-/5882483 为了清楚起见,下面是JavaScript中相同错误的示例: https : //gist.github.com/xavi-/5882483
Any idea what I should do in Java/Android? 知道我应该在Java / Android中做什么吗?
Welcome to world of synchronization. 欢迎来到同步世界。 Mutex or lock objects are often used for that purpose.
互斥锁或锁定对象通常用于此目的。 Is there a Mutex in Java?
Java中是否有Mutex?
your B task should wait on mutex which is to be signaled by task A upon its completion. 您的B任务应等待互斥量,而互斥量将在任务A完成时发出信号。 That will ensure proper execution order where A task will finish before B.
这将确保正确的执行顺序,其中A任务将在B之前完成。
Always put task.onDone()
in the AsyncTask
, even if it doesn't have to make a request. 始终将
task.onDone()
放在AsyncTask
,即使它不必发出请求也是如此。
makeRequest(SomeTask task) {
asyncTask = new AsyncTask<SomeTask, Void, Void>() {
void doInBackground(SomeTask... task) {
if(canDoOptimization) { // if true, don't need to make request
// It's a bad idea to execute this immediately.
// Wish I could wait until the current thread of was done...
task.onDone();
return;
} else {
// Make server request...
task.onDone();
}
}
}
asyncTask.execute(task);
}
Why can't you just switch the order of things? 您为什么不能只切换事物顺序?
// Do actionA with queue. Must be execute first!!
makeRequest(new SomeTask{
onDone() {
// Do actionB with queue
});
If actionA is asynchronous as well and performed on a separate AsyncTask, you can call makeRequest(...) on actionA's AsyncTasks's onPostExecute() method. 如果actionA也是异步的并且在单独的AsyncTask上执行,则可以在actionA的AsyncTasks的onPostExecute()方法上调用makeRequest(...)。
And btw, since Android Honeycomb version, AsyncTasks are ran on the same thread, meaning if you have several tasks they can block each other. 顺便说一句,从Android Honeycomb版本开始,AsyncTasks在同一线程上运行,这意味着如果您有多个任务,它们可能会相互阻塞。 This is fixed by specifying that the AsyncTsak should run in a thread pool:
通过指定AsyncTsak应该在线程池中运行来解决此问题:
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) {
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
else {
asyncTask.execute();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.