Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tento článek popisuje způsob, jakým rozhraní .NET Framework zpracovává volání z jazyka C# a kódu jazyka Visual Basic na objekty poskytované modulem Windows Runtime nebo komponentami prostředí Windows Runtime.
V rozhraní .NET Framework můžete ve výchozím nastavení přistupovat k libovolnému objektu z více vláken bez speciálního zpracování. Jediné, co potřebujete, je odkaz na objekt. V prostředí Windows Runtime se takové objekty nazývají agilní. Většina Windows Runtime tříd je flexibilní, ale několik tříd není, a dokonce i flexibilní třídy mohou vyžadovat speciální zpracování.
Pokud je to možné, modul CLR (Common Language Runtime) považuje objekty z jiných zdrojů, například prostředí Windows Runtime, jako by se jednalo o objekty rozhraní .NET Framework:
Pokud objekt implementuje rozhraní IAgileObject nebo má atribut MarshalingBehaviorAttribute s typem marshalingu MarshalingType.Agile, CLR ho považuje za agilní.
Pokud CLR může zařadit volání z vlákna, ve kterém bylo provedeno do kontextu vlákna cílového objektu, provede to transparentně.
Pokud má objekt MarshalingBehaviorAttribute atribut s MarshalingType.None, třída neposkytuje informace o zařazování. CLR nedokáže předat volání, a proto vyvolá InvalidCastException výjimku se zprávou, že objekt lze použít pouze v kontextu vlákna, kde byl vytvořen.
Následující části popisují účinky tohoto chování na objekty z různých zdrojů.
Objekty z komponenty prostředí Windows Runtime napsané v jazyce C# nebo Visual Basic
Všechny typy v komponentě, které je možné aktivovat, jsou ve výchozím nastavení agilní.
Poznámka:
Flexibilita neznamená bezpečnost vláken. V prostředí Windows Runtime i rozhraní .NET Framework nejsou většina tříd bezpečné pro vlákna, protože zajištění bezpečnosti vláken má dopad na výkon, a většina objektů není nikdy přistupována více vlákny. Je efektivnější synchronizovat přístup k jednotlivým objektům (nebo používat třídy bezpečné pro přístup z více vláken) pouze podle potřeby.
Když vytvoříte komponentu prostředí Windows Runtime, můžete výchozí nastavení přepsat. Viz ICustomQueryInterface rozhraní a IAgileObject rozhraní.
Objekty z prostředí Windows Runtime
Většina tříd v prostředí Windows Runtime je agilní a CLR je považuje za agilní. Dokumentace pro tyto třídy uvádí "MarshalingBehaviorAttribute(Agile)" mezi atributy třídy. Členové některých z těchto agilních tříd, jako jsou například ovládací prvky XAML, však můžou vyvolat výjimky, pokud nejsou volány ve vlákně uživatelského rozhraní. Například následující kód se pokusí použít vlákno na pozadí k nastavení vlastnosti tlačítka, na které jste klikli. Vlastnost Content tlačítka vyvolá výjimku.
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
K tlačítku se dostanete bezpečně pomocí jeho vlastnosti Dispatcher nebo Dispatcher vlastnosti libovolného objektu, který existuje v kontextu vlákna uživatelského rozhraní (například stránka, na které je tlačítko zapnuto). Následující kód používá metodu RunAsync objektu CoreDispatcher, aby odeslal volání ve vlákně uživatelského rozhraní.
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
Poznámka:
Vlastnost Dispatcher nevyvolá výjimku, pokud je volána z jiného vlákna.
Životnost objektu prostředí Windows Runtime, který je vytvořen ve vlákně uživatelského rozhraní, je vázán životností vlákna. Po zavření okna se nepokoušejte o přístup k objektům ve vlákně uživatelského rozhraní.
Pokud vytváříte vlastní ovládací prvek děděním ovládacího prvku XAML nebo vytvořením sady ovládacích prvků XAML, je ovládací prvek agilní, protože se jedná o objekt rozhraní .NET Framework. Pokud však volá členy své základní třídy nebo složených tříd, nebo pokud voláte zděděné členy, tyto členy vyvolají výjimky, když jsou volány z jakéhokoliv vlákna kromě vlákna uživatelského rozhraní.
Třídy, které nelze zařadovat
Třídy prostředí Windows Runtime, které neposkytují maršálovací informace, mají atribut MarshalingBehaviorAttribute s MarshalingType.None. Dokumentace pro takovou třídu uvádí "MarshalingBehaviorAttribute(None)" mezi jejími atributy.
Následující kód vytvoří CameraCaptureUI objekt ve vlákně uživatelského rozhraní a pak se pokusí nastavit vlastnost objektu z vlákna fondu vláken. CLR nemůže zařadit volání a vyvolá výjimku System.InvalidCastException se zprávou, že objekt lze použít pouze v kontextu vlákna, ve kterém byl vytvořen.
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
Dokumentace pro CameraCaptureUI také uvádí "ThreadingAttribute(STA)" mezi atributy třídy, protože se musí vytvořit v kontextu s jedním vláknem, jako je vlákno uživatelského rozhraní.
Pokud chcete získat přístup k objektu
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
Objekty z komponenty prostředí Windows Runtime napsané v jazyce C++
Ve výchozím nastavení jsou třídy v komponentě, které lze aktivovat, agilní. Jazyk C++ však umožňuje značné množství kontroly nad modely podprocesů a řízením přenosu. Jak je popsáno výše v tomto článku, CLR rozpozná agilní třídy, pokusí se zařadit volání, pokud třídy nejsou agilní, a vyvolá System.InvalidCastException výjimku, pokud třída neobsahuje žádné informace o zařazování.
U objektů, které běží ve vlákně uživatelského rozhraní a vyvolávají výjimky, když jsou volány z jiného vlákna než z vlákna uživatelského rozhraní, můžete použít objekt CoreDispatcher vlákna uživatelského rozhraní k odeslání volání.