在 Xamarin.iOS 中使用 UI 線程
應用程式使用者介面一律為單個線程,即使是在多線程裝置中, 畫面上只有一個表示法,而且任何顯示內容的變更都需要透過單一「存取點」協調。 這可防止多個線程同時嘗試更新相同的圖元(例如)。
您的程式代碼應該只對主要 (或 UI) 線程的使用者介面控件進行變更。 在不同線程上發生的任何UI更新(例如回呼或背景線程)都可能不會轉譯到畫面,甚至可能會導致當機。
UI 線程執行
當您在檢視中建立控件,或處理使用者起始的事件,例如觸控時,程式代碼已在UI線程的內容中執行。
如果程式代碼是在背景線程上執行,在工作或回呼中,它很可能不會在主要 UI 線程上執行。 在此情況下,您應該將程式代碼包裝在對的呼叫 InvokeOnMainThread
中,或 BeginInvokeOnMainThread
如下所示:
InvokeOnMainThread ( () => {
// manipulate UI controls
});
方法 InvokeOnMainThread
已定義於 上 NSObject
,因此可以從任何UIKit對象上定義的方法內呼叫它(例如 View 或 View Controller)。
偵錯 Xamarin.iOS 應用程式時,如果您的程式代碼嘗試從錯誤的線程存取 UI 控制件,將會擲回錯誤。 這可協助您追蹤並修正 InvokeOnMainThread 方法的這些問題。 這隻會在偵錯時發生,而且不會在發行組建中擲回錯誤。 錯誤訊息會顯示如下:
背景線程範例
以下是使用簡單線程從背景線程存取使用者介面控件 (a UILabel
) 的範例:
new System.Threading.Thread(new System.Threading.ThreadStart(() => {
label1.Text = "updated in thread"; // should NOT reference UILabel on background thread!
})).Start();
該程式代碼會在偵錯時擲回 UIKitThreadAccessException
。 若要修正問題(並確保使用者介面控件只能從主要 UI 線程存取),請將任何參考 UI 控制件的程式代碼包裝在運算式內 InvokeOnMainThread
,如下所示:
new System.Threading.Thread(new System.Threading.ThreadStart(() => {
InvokeOnMainThread (() => {
label1.Text = "updated in thread"; // this works!
});
})).Start();
您不需要針對本檔中的其餘範例使用此專案,但當您的應用程式提出網路要求時,請使用通知中心或其他需要完成處理程式的方法,以在另一個線程上執行,這是一個重要的概念。
Async/Await 範例
使用 C# 5 async/await 關鍵詞時並非必要, InvokeOnMainThread
因為當等候的工作完成方法時,會在呼叫線程上繼續。
這個範例程式代碼(在 Delay 方法呼叫上等候,純粹是為了示範目的)會顯示在 UI 線程上呼叫的異步方法(它是 TouchUpInside 處理程式)。 由於在UI線程上呼叫包含的方法,因此在背景線程上完成異步操作之後,可以在上 UILabel
設定文字或顯示 UIAlertView
的文字等UI作業安全地呼叫。
async partial void button2_TouchUpInside (UIButton sender)
{
textfield1.ResignFirstResponder ();
textfield2.ResignFirstResponder ();
textview1.ResignFirstResponder ();
label1.Text = "async method started";
await Task.Delay(1000); // example purpose only
label1.Text = "1 second passed";
await Task.Delay(2000);
label1.Text = "2 more seconds passed";
await Task.Delay(1000);
new UIAlertView("Async method complete", "This method",
null, "Cancel", null)
.Show();
label1.Text = "async method completed";
}
如果從背景線程呼叫異步方法(不是主要 UI 線程), InvokeOnMainThread
則仍然需要 。