2017-09-07 51 views
1

然而,使用Xamarin.Android,我不認爲這是我的問題背後的原因。爲什麼AsyncTask中的OnProgressUpdate不被調用?

我面臨的問題是OnProgressUpdate方法只在AsyncTask對象中調用一次,我正在使用它來處理後臺任務。這裏是我的課:

public class DBInflater : AsyncTask 
{ 
    private int progress; 
    private ProgressBar progressBar; 

    public DatabaseInflater(ProgressBar progressBar) 
    { 
     this.progressBar = progressBar; 
    } 

    protected override void OnPreExecute() 
    { 
     base.OnPreExecute(); 
    } 

    protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] @params) 
    { 
     System.Threading.Tasks.Task.Run([some heavy task]); 

     while (progress < 100) 
     { 
      Java.Lang.Thread.Sleep(500); 
      PublishProgress(progress); 
      progress += 1; 
     } 

     return true; 
    } 

    protected override void OnProgressUpdate(params Java.Lang.Object[] values) 
    { 
     progressBar.Progress = progress; 
    } 

    protected override void OnPostExecute(Java.Lang.Object result) 
    { 
     base.OnPostExecute(result); 
    } 
} 

我已經成功地縮小問題這一行:Java.Lang.Thread.Sleep(500); 如果我使用較小的睡眠值,OnProgressUpdate將不會在第一次後調用。我登陸500,因爲有了這個值,OnProgressUpdate被正確調用並且progressBar在屏幕上更新。

是否有一個原因,我必須在一定的時間間隔睡覺線程?我希望progressBar能夠實時更新,而不是每半秒鐘更新一次。

+3

1.您的進度是_lie_。 2.「如果我使用較小的值進行睡眠,則OnProgressUpdate將在第一次後不會被調用。」 - 如何確定? – Fildor

+0

換句話說''[一些繁重的任務]'應該'PublishProgress'到'doInBackground'線程中。 – mihail

+0

我應該澄清[某些繁重的任務]是我從共享庫調用的任務。但是,我不認爲這是問題的核心。 while循環是什麼讓我悲傷。我的代碼示例中遺漏了一些Log輸出報告傳入值[0]的值。如果我Thread.Sleep(<500),OnProgressUpdate被調用一次(我第一次稱爲PublishProgress)。下次調用OnProgressUpdate時,一旦DoInBackground完成 - 換句話說,進度== 100.當我將Thread.Sleep設置爲500或更大時,OnProgressUpdate每次都會被調用。 – hellaandrew

回答

3

運行Task線程DoInBackground方法不報告其進展沒有任何意義。

當調用DoInBackground時,您不是在UI線程上,而是後臺線程,可以通過檢查Looper.MainLooper.IsCurrentThread的值來檢查,因此使用Task.Run不是必需的。

所以一旦在DoInBackground你的DB Inflater將大概做了一系列的步驟,創建數據庫,創建表,索引等,然後加載每個表與數據等......這是由你來決定發生的進展量併發布(PublishProgress)。

在這個例子中,我有三個步驟,並在完成每一步後報告比賽增加了33%。

public class DBInflaterAsyncTask : AsyncTask 
{ 
    protected override Object DoInBackground(params Object[] @params) 
    { 
     // You are not on the UI thread 

     Task.Delay(1000); // create db 
     PublishProgress(new Object[] { 33 }); 
     Task.Delay(1000); // create tables 
     PublishProgress(new Object[] { 66 }); 
     Task.Delay(1000); // load table data 
     PublishProgress(new Object[] { 99 }); 
     return null; 
    } 

    protected override void OnProgressUpdate(params Object[] values) 
    { 
     // You are on the UI thread 

     Log.Debug("SomeTag", values[0].ToString()); 
    } 
} 
+1

當您沒有有形的整數值用作進度基準時,此答案可能是正確方法的最佳表示。所以設定你自己的進步點是最好的選擇。 – Digitalsa1nt

+0

請參考我在我的問題下編制的評論。我的問題不是後臺正在處理的內容,或者正在進行的實際進度計算。這似乎是我打電話給PublishProgress的速度。 – hellaandrew

+0

@hellaandrew調用'OnProgressUpdate'可以讓你回到UI線程,並且更新進度位置將其發送到消息隊列中,等等......如果你發佈事件的速度更快,那麼UI線程可以跟上,你會得到一個「long操作「問題(您可以在手機的開發選項中啓用可視的長時間操作閃光)。如果你記錄了OnProgressUpdate調用,除非你的AsyncTask拋出一個異常終止或者你阻塞/鎖定後臺線程,否則他們不會被調用。 – SushiHangover

相關問題