2012-07-31 65 views
0

我在我的代碼下面使用thread.join時遇到問題。它應該等待線程完成之後才能執行代碼,對吧?在不同的場合表現不同。android多線程:thread.join()不能正常工作

我有三種情況檢查我的代碼順利

  • 應用程序用於第一次 - 按預期工作,但同時下載
  • 應用程序加載頁面不會出現使用第二時間(db是最新的) - 工作好
  • 應用程序使用了第三次(DB已經過時,必須更新) - 將不會更新,屏幕變黑,然後崩潰

我想我有與問題在onCreate方法S碼:

dropOldSchedule(); 
dropThread.join(); 
triggerDownload(); 

基於日誌,代碼工作,直到該部分之前...什麼可能是問題嗎?


MainActivity.java

public class MainActivity extends Activity { 

final static int INDEX_ACCTTYPE = 0; 
final static int INDEX_ECN = 1; 
final static int INDEX_TLN = 2; 
final static int INDEX_SIN = 3; 
final static int INDEX_MOBILE = 4; 
final static int INDEX_CITY = 5; 
final static int INDEX_START_DATE = 6; 
final static int INDEX_START_TIME = 7; 
final static int INDEX_END_DATE = 8; 
final static int INDEX_END_TIME = 9; 
final static int INDEX_REASON = 10; 
final static int INDEX_DETAILS = 11; 

DatabaseHandler db; 
String str; 
ProgressDialog pd; 

TextView homeText1, homeText2, homeText3, homeText4; 

final private String csvFile = "http://www.meralco.com.ph/pdf/pms/pms_test.csv"; 
final private String uploadDateFile = "http://www.meralco.com.ph/pdf/pms/UploadDate_test.txt"; 

Thread dropThread = new Thread(new Runnable() { 

    public void run() { 
     db = new DatabaseHandler(MainActivity.this); 
     db.dropOldSchedule(); 

     runOnUiThread(new Runnable() { 
      public void run() { 
       while (!pd.isShowing()); 
       db.close(); 
       pd.dismiss(); 
      } 
     }); 
    } 

}); 
Thread getUploadDateThread = new Thread(new Runnable() { 

    public void run() { 

     try { 
      URL myURL = new URL(uploadDateFile); 

      BufferedReader so = new BufferedReader(new InputStreamReader(myURL.openStream())); 
      while (true) { 
       String output = so.readLine(); 
       if (output != null) { 
        str = output; 
       } 
       else { 
        break; 
       } 
      } 
     so.close(); 
     } 
     catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     runOnUiThread(new Runnable() { 
      public void run() { 
       while (!pd.isShowing()); 
       pd.dismiss(); 
      } 
     }); 
    } 

    }); 
Thread downloadThread = new Thread(new Runnable() { 

    public void run() { 

     db = new DatabaseHandler(MainActivity.this); 
     db.beginTransaction(); 

     try { 
      URL url = new URL(csvFile); 

      Log.i("dl", "start"); 

      InputStream input = url.openStream(); 
      CSVReader reader = new CSVReader(new InputStreamReader(input)); 
      Log.i("dl", "after reading"); 

      String [] sched; 
      while ((sched = reader.readNext()) != null) { 
       if(sched[INDEX_CITY].equals("")) sched[INDEX_CITY]="OTHERS"; 
       try { 

        db.addRow(sched[INDEX_SIN], sched[INDEX_CITY], 
          sched[INDEX_START_DATE], sched[INDEX_START_TIME], 
          sched[INDEX_END_DATE], sched[INDEX_END_TIME], 
          sched[INDEX_DETAILS], sched[INDEX_REASON]); 
       } catch (IndexOutOfBoundsException e) { 
        db.addRow(sched[INDEX_SIN], sched[INDEX_CITY], 
          sched[INDEX_START_DATE], sched[INDEX_START_TIME], 
          sched[INDEX_END_DATE], sched[INDEX_END_TIME], 
          "", sched[INDEX_REASON]); 
        //e.printStackTrace(); 
       } 
      } 
      input.close(); 
      Log.i("dl", "finished"); 

     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
      db.endTransaction(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      db.endTransaction(); 
     } 
     Log.d("Count", ""+db.count()); 
     db.setTransactionSuccessful(); 
     db.endTransaction(); 

     writeUploadDateInTextFile(); 

    } 

}); 

@SuppressWarnings("unqualified-field-access") 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.pms_main); 

    Button home = (Button) findViewById(R.id.home); 
    home.setOnClickListener(new OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      Intent intent = new Intent(MainActivity.this, MeralcoSuite_TabletActivity.class); 
      intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
      startActivity(intent); 

      finish(); 
     } 
    }); 

    homeText1 = (TextView) findViewById(R.id.home_text1); 
    homeText2 = (TextView) findViewById(R.id.home_text2); 
    homeText3 = (TextView) findViewById(R.id.home_text3); 
    homeText4 = (TextView) findViewById(R.id.home_text4); 

    homeText1.setVisibility(View.INVISIBLE); 
    homeText2.setVisibility(View.INVISIBLE); 
    homeText3.setVisibility(View.INVISIBLE); 
    homeText4.setVisibility(View.INVISIBLE); 

    getUploadDate(); 
    try { 
     getUploadDateThread.join();  //wait for upload date 

     Log.d("getUploadDate","thread died, upload date=" + str); 

     if(dbExists()){ 
      db = new DatabaseHandler(MainActivity.this); 
      Log.d("Count", "" + db.count()); 
      db.close(); 

      if(!uploadDateEqualsDateInFile()){ 
       dropOldSchedule(); 
        dropThread.join(); 
       triggerDownload(); 
      } 
      showDisclaimer(); 
      Log.i("oncreate", "finished!"); 
      return; 
     } 

     triggerDownload(); 
     showDisclaimer(); 
     Log.i("oncreate", "finished!"); 

    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 

public void dropOldSchedule(){ 

    if(pd!=null && pd.isShowing()) 
     pd.setTitle("Getting upload date..."); 
    else 
     pd = ProgressDialog.show(this, "Getting upload date", 
      "This may take a few minutes...", true, false); 


    dropThread.start(); 
} 
public void triggerDownload() { 

    if (!checkInternet()) { 
     showAlert("An internet connection is required to perform an update, please check that you are connected to the internet"); 
     return; 
    } 

    if(pd!=null && pd.isShowing()) 
     pd.setTitle("Getting upload date..."); 
    else 
     pd = ProgressDialog.show(this, "Getting upload date", 
      "This may take a few minutes...", true, false); 

    downloadThread.start(); 

} 

public void getUploadDate() { 

    Log.d("getUploadDate", "getting upload date of schedule"); 

    if(pd!=null && pd.isShowing()) 
     pd.setTitle("Getting upload date..."); 
    else 
     pd = ProgressDialog.show(this, "Getting upload date", 
      "This may take a few minutes...", true, false); 


    getUploadDateThread.start(); 

} 

public void writeUploadDateInTextFile() { 
    Log.d("writeUploadDateTextFile", "writing:"+str); 

    try { 
     OutputStreamWriter out = new OutputStreamWriter(openFileOutput(
       "update.txt", 0)); 
     out.write(str); 
     out.close(); 
    } catch (java.io.IOException e) { 
     e.printStackTrace(); 
    } 
} 

public void showDisclaimer() { 
    Log.d("ShowDisclaimer", "showing disclaimer"); 

    homeText3 
    .setText("..." + str 
      + "..."); 


    homeText1.setVisibility(View.VISIBLE); 
    homeText2.setVisibility(View.VISIBLE); 
    homeText3.setVisibility(View.VISIBLE); 
    homeText4.setVisibility(View.VISIBLE); 

    Log.d("showDisclaimer", "finished showing disclaimer"); 

} 

public boolean uploadDateEqualsDateInFile() { 
    Log.d("uploadDateEqualsDateInFile","comparing schedule upload dates"); 

    try { 
      String recordedDate = ""; 
      InputStream instream = openFileInput("update.txt"); 
      if (instream != null) { // if file the available for reading 
       Log.d("uploadDateEqualsDateInFile","update.txt found!"); 

       InputStreamReader inputreader = new InputStreamReader(instream); 
       BufferedReader buffreader = new BufferedReader(inputreader); 

       String line = null; 
       while ((line = buffreader.readLine()) != null) { 
        recordedDate = line; 
        Log.d("uploadDateEqualsDateInFile","recorded:"+recordedDate); 
       } 

       Log.d("uploadDateEqualsDateInFile","last upload date: " + str + ", recorded:" +recordedDate); 

       if(str.equals(recordedDate)) return true; 
       return false; 
      } 
      Log.d("uploadDateEqualsDateInFile","update.txt is null!"); 
      return false; 

    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
     return false; 
    } catch (IOException e) { 
     e.printStackTrace(); 
     return false; 
    } 
} 

public boolean checkInternet() { 
    ConnectivityManager cm = (ConnectivityManager) this 
      .getSystemService(Context.CONNECTIVITY_SERVICE); 

    NetworkInfo infos[] = cm.getAllNetworkInfo(); 

    for (NetworkInfo info : infos) 
     if (info.getState() == NetworkInfo.State.CONNECTED 
       || info.getState() == NetworkInfo.State.CONNECTING) { 
      return true; 
     } 

    return false; 
} 

public boolean dbExists() { 

    File database=getApplicationContext().getDatabasePath(DatabaseHandler.DATABASE_NAME); 

    if (!database.exists()) { 
     Log.i("Database", "Not Found"); 
     return false; 
    } 

    Log.i("Database", "Found"); 
    return true; 

} 

@Override 
protected void onDestroy() { 
    super.onDestroy(); 
    if (db != null) { 
     db.close(); 
    } 
} 
@Override 
protected void onPause() { 
    super.onPause(); 
    if (db != null) { 
     db.close(); 
    } 
} 

}

+0

任何理由,你爲什麼不能做所有這些都包含在的AsyncTask? – Jimmy 2012-07-31 12:14:30

+0

並不建議在此處發佈整個代碼。 – 2012-07-31 12:17:13

+0

@ James.Elsey,我正在處理它,但我仍然想知道這個代碼有什麼問題.. Andro,會盡量不要下次,但我認爲這會更容易,如果他們可以看到代碼..我不太確定它出錯的地方。 – yojoannn 2012-07-31 12:22:54

回答

2

很抱歉,但我無法找到代碼中的錯誤或問題。但我強烈建議您使用AsyncTask在不同的線程中執行某些操作。 AsyncTask非常易於使用,我會說它是java最大的優點之一。我真的很想念obj-c。

http://labs.makemachine.net/2010/05/android-asynctask-example/

http://marakana.com/s/video_tutorial_android_application_development_asynctask_preferences_and_options_menu,257/index.html

檢查這些鏈接希望會幫助你。

1

已經提到AsyncTask是更好的選擇。但是,可能會出現這種情況,您的加入電話將會丟失InterruptedException。嘗試使用這樣的:

while(getUploadDateThread.isRunning()){ 
    try{ 
     getUploadDateThread.join(); 
    } catch (InterruptedException ie){} 
} 
// code after join 
-1

的Thread.join的整點是要確保所有過程取其線程您與當前的執行,然後再繼續加入完整。

如果你剛剛關閉一個程序,並希望確保在結束之前進行存儲等操作,那真的很有意義。使用線程。加入你的onCreate在這個意義上並沒有真正的幫助。

對不起,我知道它並沒有清除你的疑問,但確保你知道爲什麼使用thread.join!

+0

根據社區準則,上述意見可作爲評論發佈。答案部分只發布答案。 – Hemanth 2012-12-23 09:32:17

0

我認爲你面臨的問題是當你在onCreate()方法中調用加入時你阻塞了UI線程。你應該將這段代碼移動到另一個應該在後臺執行的線程中,一旦完成,你可以更新UI。

這裏是一個示例代碼:

final Thread t1 = new Thread(); 
    final Thread t2 = new Thread(); 
    t1.start(); 
    t2.start(); 
    new Thread(new Runnable() { 

     @Override 
     public void run() { 
      // Perform all your thread joins here. 
      try { 
       t1.join(); 
       t2.join(); 
      } catch (Exception e) { 
       // TODO: handle exception 
      } 


      // This thread wont move forward unless all your threads 
      // mentioned above are executed or timed out. 
      // ------ Update UI using this method 
      runOnUiThread(new Runnable() { 

       @Override 
       public void run() { 
        // Update UI code goes here 

       } 
      }); 

     } 
    }).start();