2016-08-13 12 views
0

我正在使用Gtk#創建簡單的桌面應用程序,當用戶單擊按鈕時我想顯示「加載指示器」MessageDialog並使一些在後臺處理時,當進程完成時關閉對話框並從UI更新一些控件。如何在執行後臺進程時顯示MessageDialog並在完成後關閉它

我很新的Gtk#和Mono,所以我的代碼如下所示:

protected void OnBtnClicked(object sender, EventArgs e) 
{ 
    try 
    { 
     Task.Factory.StartNew(() => 
     { 
      var dlg = new MessageDialog(this, DialogFlags.Modal, MessageType.Info, ButtonsType.None, "Processing..."); 
      dlg.Run();   

      //Some sync calls to remote services 
      //... 

      //The process finished so close the Dialog 
      dlg.Destroy(); 

      //Here: Update the UI with remote service's response 
      //txtResult.Buffer.Text = result.Message; 
     }); 
    } 
    catch (Exception ex) 
    { 
     var dlg = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.Close, ex.Message); 
     dlg.Title = "Error"; 
     dlg.Run(); 
     dlg.Destroy(); 
    } 
} 

此代碼顯示MessageDialog,但它永遠不會關閉。

單聲道版本:4.4.2

IDE:Xamarin Studio的社區版6.0.2

Gtk#的版本:38年2月12日

回答

0

閱讀響應單應用guide,並要求米格爾後通過Twitter通過我找到了這樣做的方式。

事情要考慮到:

1)不要創建或嘗試修改從另一個線程的UI元素。 2)如果您需要從另一個線程修改UI控件,請使用該線程內的Application.Invoke()方法。

3)MessageDialog類的Run()方法等待用戶交互關閉,即單擊關閉按鈕或調用Close/Destroy事件的東西。在這種情況下使用該方法是錯誤的,因爲我將從我的代碼中關閉MessageDialog,所以顯示對話框的正確方法是Show()。

有了,在我的腦海裏,我的最終代碼如下所示:

protected void OnBtnClicked(object sender, EventArgs e) 
{ 
    try 
    { 
     var mdCalculate = new MessageDialog(this, DialogFlags.Modal, MessageType.Info, ButtonsType.None, "Processing..."); 
     mdCalculate.Title = "Calculate"; 
     mdCalculate.Show(); 

     Task.Factory.StartNew(() => 
     { 
      //Some sync calls to remote services 
      //... 

      //returns the data I will show in the UI, lets say it's a string 
      return someData; 
     }).ContinueWith((prevTask) => 
     { 
      Application.Invoke((send, evnt) => 
      { 
       txtResult.Buffer.Text = prevTask.Result; //this is the string I returned before (someData) 
       mdCalculate.Hide(); 
       mdCalculate.Destroy(); 
      }); 
     }); 
    } 
    catch (Exception ex) 
    { 
     var dlg = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.Close, ex.Message); 
     dlg.Title = "Error"; 
     dlg.Run(); 
     dlg.Destroy(); 
    } 
} 

演示:

enter image description here

相關問題