我制作了一个Android应用程序,通过Asynctask在服务器上进行身份验证,在后台点击用户按钮时执行此操作。发生这种情况时,会向用户显示加载弹出窗口或微调器。这一切目前都在运作。
我现在正试图通过设置另一台服务器来创建冗余,以防第一台服务器出现故障。为了适应我的应用程序的这种变化,我想到让2个asynctasks一个接一个地调用。
但是,我遇到了一些问题。
作为测试网址,我一直在使用 10.255.255.1 (不可路由的地址)和 www.google.com:81 (阻止的端口,丢弃的数据包)。
如果服务器1没有响应或需要很长时间(使用上面的网址测试),我试图在asynctask上做一个计时器5-10秒,我尝试过使用
new MyAsyncTask().execute(serverurl1).get(5000, TimeUnit.MILLISECONDS);
它不起作用。奇怪的是,它在显示旋转轮之前等待了5秒,然后正常执行(等待永远超过5秒甚至10秒标记)。
我想这第二个问题取决于第一个问题但是如何在创建第二个asynctask来查询服务器2之前确保第一个asynctask已经完成(或者已经执行并超过了时间限制)?我想我可以使用STATUS.running(但只有在确定第一个asynctask已经运行之后?
对于这个,我试过像这样拍摄2个asynctasks:
new MyAsyncTask().execute(serverurl1);
new MyAsyncTask().execute(serverurl2);
希望拍摄2个asynctasks会让我得到某种回应。即使1失败了,我们仍然会通过身份验证,但是唉,它没有用。
我知道有些人可能会说通过序列化asynctask的行为,然后它就会失败它的目的。当应用程序使用服务器检查自己时,我用它来显示屏幕上的微调器。
问题:
我理想的解决方案是:
用户点击按钮
asynctask 1运行并查询服务器1
如果出现问题,asynctask 1在计时器用完后被杀死
asynctask 2然后运行查询到服务器2
如果出现问题,asynctask 2会在计时器用完后被杀死
(没有永久运行的进程并显示清除错误消息)
或
用户点击按钮
asynctask 1运行并查询服务器1
如果出现问题,asynctask 1在计时器用完后被杀死
然后通知用户重试(在内部设置标志以查询服务器2)
用户再次点击按钮
asynctask 2然后运行查询到服务器2
如果出现问题,asynctask 2会在计时器用完后被杀死
(同样,没有永久运行的进程并显示清除错误消息)
感谢。
我使用:
调用异步块private void startTask() throws IOException {
String url = "http://google.com:81";
//String url = "http://10.255.255.1";
String url2 = "someurlthatworks";
// tried this
new MyAsyncTask().execute(url);
new MyAsyncTask().execute(url2);
// and this
try {
new MyAsyncTask().execute(url).get(5000, TimeUnit.MILLISECONDS);
}catch(Exception e){}
}
我在How can I put a timer in an AsyncTask without creating another thread?上看到了这一点(用我的变量编辑):
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
new MyAsyncTask.execute(url);
}
}, 5000);
它适用于我的问题吗?
这是我的asynctask代码块: class MyAsyncTask扩展了AsyncTask {
@Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(DIALOG_DOWNLOAD_PROGRESS);
}
@Override
protected String doInBackground(String... urls) {
int count;
InputStream input = null;
HttpURLConnection httpconnection = null;
try {
URL url = new URL(urls[0]);
httpconnection = (HttpURLConnection) url.openConnection();
httpconnection.connect();
httpconnection.setConnectTimeout(7000);
httpconnection.setReadTimeout(10000);
// check here if there is connectivity, server is accessible, http code is 200
// return error message if any of the above not found
int lengthOfFile = httpconnection.getContentLength();
input = httpconnection.getInputStream();
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress(""+(int)((total*100)/lengthOfFile));
}
String msg = new String(data);
if(msg.contains(someinfo)) {
allow = true;
}
input.close();
} catch (Exception e) {}
return null;
}
protected void onProgressUpdate(String... progress) {
mProgressDialog.setProgress(Integer.parseInt(progress[0]));
}
@Override
protected void onPostExecute(String unused) {
dismissDialog(DIALOG_DOWNLOAD_PROGRESS);
if(allow){
Toast.makeText(getBaseContext(),"Success",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getBaseContext(),"Failed",Toast.LENGTH_SHORT).show();
}
}
}
我被告知
httpconnection.setConnectTimeout(7000);
httpconnection.setReadTimeout(10000);
应该适用于我的问题,但不知何故它不会,asynctask只是等待。
更新
正如MarcinJędrzejewski所建议的,我在连接之前移动连接和读取超时,我得到:
... [socket][1] - [socket][13] here ...
[socket][14:42141] exception
[CDS]close[42141]
close [socket][/0.0.0.0:42141]
[socket][14] connection www.google.com/4.35.153.212:81;LocalPort=59339(7000)
[CDS]connect[www.google.com/4.35.153.212:81] tm:7
[socket][15:59339] exception
[CDS]close[59339]
close [socket][/0.0.0.0:59339]
[socket][15] connection www.google.com/4.35.153.237:81;LocalPort=56148(7000)
[CDS]connect[www.google.com/4.35.153.237:81] tm:7
[socket][16:56148] exception
[CDS]close[56148]
setconnecttimeout似乎是每次尝试连接时的超时,但有没有办法设置重试连接的次数而不是总是进行16次尝试?
答案 0 :(得分:2)
您可以在docs中读取,AsyncTask.get将抛出TimeoutException,以防时间已过,但没有结果。我的建议是在您的Url连接上添加超时(如果您使用它),例如:
httpUrlConnection.setConnectTimeout(5000);
httpUrlConnection.setReadTimeout(5000);
这将导致您的Url连接在5秒后解锁,然后您的AsyncTask也将完成。然后在onPostExecute中,您可以使用新的Url执行另一个AsyncTask - 如果连接错误。
如果您想中止当前连接 - 正在进行中 - 请使用:
httpUrlConnection.disconnect();
最后,调用AsyncTask.get()并不是一个好主意,正如我上面所描述的那样 - 它并不能保证连接将会终止,而且你也无法在UI线程上调用它。
答案 1 :(得分:0)
所以我找到了这个话题How to timeout Asynctask and dismiss ProgressDialog?
我在下面的doInBackground中实现了我的代码:
long waitTime = 7000;
long curWaitTime = 0;
while (!timeout && curWaitTime < waitTime){
// put your network/file code here
// if the data finishes then you can set timeout to true
try {
URL url = new URL(urls[0]);
httpconnection = (HttpURLConnection) url.openConnection();
httpconnection.setConnectTimeout(7000);
httpconnection.setReadTimeout(9000);
httpconnection.connect();
// check here if there is connectivity, server is accessible, http code is 200
// return error message if any of the above not found
input = httpconnection.getInputStream();
byte data[] = new byte[1024];
input.read(data);
String msg = new String(data);
if (msg.contains(someinfo)){
allow = true;
timeout = true;
}
input.close();
} catch (Exception e) {}
curWaitTime += 7000;
try{
Thread.sleep(100);
}catch(Exception e){}
}
我将waitTime设置为与setConnectTimeout相同,这使得while循环在1次连接尝试后大致超时。
我的startTask()基本上只是
new MyAsyncTask().execute(url);
使用一些标志让应用知道第一个asynctask是否失败,所以它可以尝试:
new MyAsyncTask().execute(url2);
不确定thread.sleep(100)的用途。我知道线程在每个while循环后休眠100毫秒。代码块在没有它的情况下仍可正常工作。