2011-12-12 99 views
2

我使用AsyncTask通过互联网下载数据,我有一个小问题。我需要能够几次启动一个AsyncTask,这就是为什么我每次都创建一个新实例的原因,但我注意到的是,前三到四次它没有任何问题,但在此之后,我的AsyncTask之后停滞在onPreExecute()之后。难道我做错了什么 ? (实际上,我为了测试目的一个接一个地使用两个AsyncTasks)。下面是我使用的示例代码:Android异步任务停止运行几次后运行

我这是怎么开始AsyncTasks:

if (index == 1) { 
     //Login - first way 
     new FirstSync().execute(Synchronization.this); 
    } else if (index == 2) { 
     //SyncWithHash - second way 
     SyncWithHash syncHash = new SyncWithHash(); 
     syncHash.execute(Synchronization.this); 
    } else if (index == 3) { 
     //Deactivate Collection - third way 
     deactivateColl = new DeactivateCollection(); 
     deactivateColl.execute(Synchronization.this); 
    } 

我曾尝试用三种不同的方式来启动的AsyncTask,但没有任何变化。这是我的AsyncTask:

// Sync With Hash 
public class SyncWithHash extends AsyncTask <Context, Integer, Void> { 
    @Override 
    protected Void doInBackground(Context... arrContext) { 
     try { 

      String charset = "UTF-8"; 
      hash = getAuthHash(); 

      SharedPreferences lastUser = PreferenceManager.getDefaultSharedPreferences(Synchronization.this); 
      int userId = lastUser.getInt("lastUser", 1); 

      systemDbHelper = new SystemDatabaseHelper(Synchronization.this, null, 1); 
      systemDbHelper.initialize(Synchronization.this); 
      String sql = "SELECT dbTimestamp FROM users WHERE objectId=" + userId; 
      Cursor cursor = systemDbHelper.executeSQLQuery(sql); 
      if (cursor.getCount() < 0) { 
       cursor.close(); 
      } else if (cursor.getCount() > 0) { 
       cursor.moveToFirst(); 
       timeStamp = cursor.getString(cursor.getColumnIndex("dbTimestamp")); 
       Log.d("", "timeStamp : " + timeStamp); 
      } 

       String query = String.format("debug_data=%s&" 
         + "client_auth_hash=%s&" + "timestamp=%s&" 
         + "client_api_ver=%s&" 
         + "set_locale=%s&" + "device_os_type=%s&" 
         + "device_sync_type=%s&" 
         + "device_identification_string=%s&" 
         + "device_identificator=%s&" + "device_resolution=%s", 
         URLEncoder.encode("1", charset), 
         URLEncoder.encode(hash, charset), 
         URLEncoder.encode(timeStamp, charset), 
         URLEncoder.encode(clientApiVersion, charset), 
         URLEncoder.encode(locale, charset), 
         URLEncoder.encode(version, charset), 
         URLEncoder.encode("14", charset), 
         URLEncoder.encode(version, charset), 
         URLEncoder.encode(deviceId, charset), 
         URLEncoder.encode(resolution, charset)); 

      SharedPreferences useSSLConnection = PreferenceManager 
        .getDefaultSharedPreferences(Synchronization.this); 
      boolean useSSl = useSSLConnection.getBoolean("UseSSl", true); 
      if (useSSl) { 
       UseHttpsConnection(url, charset, query); 
      } else { 
       UseHttpConnection(url, charset, query); 
      } 
     } catch (Exception e2) { 
      e2.printStackTrace(); 
     } 
     return null; 
    } 

    @Override 
    protected void onProgressUpdate(Integer... progress) { 
     //cancelDialog.setProgress(progress[0]); 
    } 
    @Override 
    protected void onCancelled() { 
     Log.d("","ON CANCELLED"); 
    } 
    @Override 
    protected void onPreExecute() 
    { 
     Log.d("","ON PRE EXECUTE"); 
     // myProgress = 0; 
    } 
    @Override 
    protected void onPostExecute(Void v) { 
     Log.d("","ON POST EXECUTE"); 
    } 
    } 

因此,任何想法,为什么它的发生,并且是能够使用的AsyncTask几次没有任何异常,盲蝽象的一个,我得到的最好方式。

另一个问题:AsyncTask中是否有任何可能导致我的连接为Reset by peer的问题,因为我也收到了这个错误(不是每次都是这样)。

非常感谢!

+0

你好夸张,你有没有注意到,如果任何你的asynk线程从服务器获得响应? –

+0

其实每个asynctask都会在开始时得到响应,但经过几次运行后,它们会停留在'onPreExecute'中,甚至不会在开始时显示来自'doInBackground'的日志。 –

+0

你能解释一下你在问题中使用的getDefaultSharedPreferences(Synchronization.this)吗? –

回答

1

我觉得你的doInBackground()是挂。让日志语句当它进入并退出并检查时

在过去的AsyncTask有一个线程池,所以如果一个doInBackground()挂起,那么它并没有影响其他AsyncTasks。这改变了AFAIK与Android 2.2或2.3 单线程照顾所有AyncTasks,一次一个。因此,如果你的doInBackground()被挂起,它可能是af对于正在启动的下一个AsyncTasks会产生影响,并且会在onPreExecute()后立即挂起。

编辑:它从单个线程更改为多个,然后返回到单个线程: http://developer.android.com/reference/android/os/AsyncTask.html#execute%28Params...%29“首次引入时,AsyncTasks在单个后台线程上被串行执行,从DONUT开始,它被更改为一个线程池允许多个任务并行运行,HONEYCOMB之后,计划将它改回单线程,以避免由于并行执行导致的常见应用程序错误。

如果你真的想要无限期的东西在parralel中“挂起”,那么不要使用AsyncTask。用好老线程,当他们需要更新的GUI,断火一个Runnable GUI线程上要拼命地跑:

Button knap1, knap2, knap3; 
... 

    Runnable r=new Runnable() { 
    public void run() { 
     // Do some stuff than hangs 
     try { Thread.sleep(10000); } catch (InterruptedException ex) {} 
     System.out.println("færdig!"); 

     // Update GUI thread 
     Runnable r2=new Runnable() { 
     public void run() { 
      knap3.setText("færdig!"); 
     } 
     }; 
     runOnUiThread(r2); 
    } 
    }; 
    new Thread(r).start(); 

(例如,从http://code.google.com/p/android-eksempler/source/browse/trunk/AndroidElementer/src/eks/asynkron/Asynkron1Thread.java?spec=svn109&r=109

+0

你知道任何可以帮助我解决问题的方法吗? –

+0

最好的办法是更改您的代码,以便网络操作在一段时间后超时。它在你的UseHttpsConnection()和UseHttpConnection()中,你没有发布需要做出的改变。如果你使用HttpURLConnection,那么建立一个setConnectTimeout(10000);让它在10秒后超时。 如果你真的想要无限期的东西在parralel中“挂起”,那么不要使用AsyncTask。使用良好的旧线程,并看到我的示例代码上面 –

+0

其实这是我改变我的AsyncTask的方式 - 现在使用线程,所以谢谢你的答案!我已经做到了。 –

0

它可能发生的,因为你是一个对象“Synchronization.this'上同步。 也注意到您不关闭您打开光标。