2011-12-12 98 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'上同步。 也注意到您不關閉您打開光標。