Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Artikel ini membahas cara .NET Framework menangani panggilan dari kode C# dan Visual Basic ke objek yang disediakan oleh Windows Runtime atau oleh komponen Windows Runtime.
Dalam .NET Framework, Anda dapat mengakses objek apa pun dari beberapa utas secara default, tanpa penanganan khusus. Yang Anda butuhkan hanyalah referensi ke objek . Di Windows Runtime, objek tersebut disebut agile. Sebagian besar kelas Windows Runtime lincah, tetapi beberapa kelas tidak, dan bahkan kelas yang gesit mungkin memerlukan penanganan khusus.
Jika memungkinkan, runtime bahasa umum (CLR) memperlakukan objek dari sumber lain, seperti Windows Runtime, seolah-olah itu adalah objek .NET Framework:
Jika objek mengimplementasikan antarmuka IAgileObject, atau memiliki atribut MarshalingBehaviorAttribute dengan MarshalingType.Agile, maka CLR memperlakukannya sebagai gesit.
Jika CLR dapat memproses panggilan dari utas tempat panggilan dibuat ke konteks utas objek target, ia melakukannya secara otomatis dan jelas.
Jika objek memiliki atribut MarshalingBehaviorAttribute dengan MarshalingType.None, kelas tidak memberikan informasi marshaling. CLR tidak dapat memproses panggilan, oleh karena itu, menghasilkan pengecualian InvalidCastException beserta pesan yang menjelaskan bahwa objek tersebut hanya bisa digunakan dalam konteks thread di mana objek tersebut dibuat.
Bagian berikut menjelaskan efek perilaku ini pada objek dari berbagai sumber.
Objek dari komponen Windows Runtime yang ditulis dalam C# atau Visual Basic
Semua jenis dalam komponen yang dapat diaktifkan bersifat agile secara default.
Nota
Agilitas tidak berarti aman utas. Di Windows Runtime dan .NET Framework, sebagian besar kelas tidak aman untuk diakses oleh banyak utas karena keamanan saat diakses oleh banyak utas memiliki biaya performa, karena sebagian besar objek biasanya tidak diakses oleh lebih dari satu utas. Lebih efisien untuk menyinkronkan akses ke objek individual (atau menggunakan kelas thread-safe) hanya jika diperlukan.
Saat Anda menulis komponen Windows Runtime, Anda dapat mengambil alih default. Lihat antarmuka ICustomQueryInterface dan antarmuka IAgileObject.
Objek dari Windows Runtime
Sebagian besar kelas-kelas dalam lingkungan Windows Runtime adalah lincah, dan CLR memperlakukannya sebagai lincah. Dokumentasi untuk kelas-kelas ini mencantumkan "MarshalingBehaviorAttribute(Agile)" di antara atribut kelas. Namun, anggota dari beberapa kelas tangkas ini, seperti kontrol XAML, akan memunculkan pengecualian jika mereka tidak dipanggil pada utas UI. Misalnya, kode berikut mencoba menggunakan utas latar belakang untuk mengatur properti tombol yang diklik. Properti Content pada tombol menimbulkan pengecualian.
private async void Button_Click_2(object sender, RoutedEventArgs e)
{
Button b = (Button) sender;
await Task.Run(() => {
b.Content += ".";
});
}
Private Async Sub Button_Click_2(sender As Object, e As RoutedEventArgs)
Dim b As Button = CType(sender, Button)
Await Task.Run(Sub()
b.Content &= "."
End Sub)
End Sub
Anda dapat mengakses tombol dengan aman dengan menggunakan properti Dispatcher, atau properti Dispatcher dari objek apa pun yang ada dalam konteks utas UI (seperti halaman tempat tombol itu berada). Kode berikut menggunakan metode CoreDispatcher objek RunAsync untuk mengirimkan panggilan pada utas UI.
private async void Button_Click_2(object sender, RoutedEventArgs e)
{
Button b = (Button) sender;
await b.Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.Normal,
() => {
b.Content += ".";
});
}
Private Async Sub Button_Click_2(sender As Object, e As RoutedEventArgs)
Dim b As Button = CType(sender, Button)
Await b.Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.Normal,
Sub()
b.Content &= "."
End Sub)
End Sub
Nota
Properti Dispatcher tidak melemparkan pengecualian ketika dipanggil dari utas lain.
Umur objek Windows Runtime yang dibuat pada utasan UI terkait dengan umur utasan itu. Jangan mencoba mengakses objek pada utas UI setelah jendela ditutup.
Jika Anda membuat kontrol Anda sendiri dengan mewarisi kontrol XAML, atau dengan menyusun sekumpulan kontrol XAML, kontrol Anda gesit karena ini adalah objek .NET Framework. Namun, jika memanggil anggota kelas dasar atau kelas konstituennya, atau jika Anda memanggil anggota yang diwariskan, anggota tersebut akan melemparkan pengecualian ketika mereka dipanggil dari utas apa pun kecuali utas UI.
Kelas yang tidak dapat dinaungi
Kelas Windows Runtime yang tidak menyediakan informasi marshaling memiliki atribut MarshalingBehaviorAttribute dengan MarshalingType.None. Dokumentasi untuk kelas tersebut mencantumkan "MarshalingBehaviorAttribute(None)" di antara atributnya.
Kode berikut membuat objek CameraCaptureUI pada utas antarmuka pengguna, lalu mencoba mengatur properti objek dari thread thread pool. CLR tidak dapat melakukan marshal panggilan, dan melempar System.InvalidCastException pengecualian dengan pesan yang menunjukkan bahwa objek hanya dapat digunakan dalam konteks utas tempat objek dibuat.
Windows.Media.Capture.CameraCaptureUI ccui;
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
ccui = new Windows.Media.Capture.CameraCaptureUI();
await Task.Run(() => {
ccui.PhotoSettings.AllowCropping = true;
});
}
Private ccui As Windows.Media.Capture.CameraCaptureUI
Private Async Sub Button_Click_1(sender As Object, e As RoutedEventArgs)
ccui = New Windows.Media.Capture.CameraCaptureUI()
Await Task.Run(Sub()
ccui.PhotoSettings.AllowCropping = True
End Sub)
End Sub
Dokumentasi untuk CameraCaptureUI juga mencantumkan "ThreadingAttribute(STA)" di antara atribut kelas, karena harus dibuat pada konteks thread tunggal seperti thread UI.
Jika Anda ingin mengakses objek
Windows.Media.Capture.CameraCaptureUI ccui;
private async void Button_Click_3(object sender, RoutedEventArgs e)
{
ccui = new Windows.Media.Capture.CameraCaptureUI();
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
() => {
ccui.PhotoSettings.AllowCropping = true;
});
}
Dim ccui As Windows.Media.Capture.CameraCaptureUI
Private Async Sub Button_Click_3(sender As Object, e As RoutedEventArgs)
ccui = New Windows.Media.Capture.CameraCaptureUI()
Await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
Sub()
ccui.PhotoSettings.AllowCropping = True
End Sub)
End Sub
Objek dari komponen Windows Runtime yang ditulis dalam C++
Secara bawaan, kelas dalam komponen yang dapat diaktifkan bersifat tangkas. Namun, C++ memungkinkan sejumlah besar kontrol atas model utas dan perilaku marshaling. Seperti yang dijelaskan sebelumnya dalam artikel ini, CLR mengenali kelas yang lincah, mencoba memarshalkan panggilan ketika kelas tidak lincah, dan melemparkan pengecualian System.InvalidCastException ketika kelas tidak memiliki informasi pemrosesan marshaling.
Untuk objek yang berjalan pada utas UI dan melemparkan pengecualian saat dipanggil dari utas selain utas UI, Anda dapat menggunakan utas UI CoreDispatcher objek untuk mengirimkan panggilan.