Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Ez a cikk azt ismerteti, hogyan kezeli a .NET-keretrendszer a C# és a Visual Basic kódból érkező hívásokat a Windows Futtatókörnyezet vagy a Windows Futtatókörnyezet összetevői által biztosított objektumokhoz.
A .NET-keretrendszerben alapértelmezés szerint több szálból is elérheti az objektumokat speciális kezelés nélkül. Mindössze az objektumra mutató hivatkozásra van szüksége. A Windows futtatókörnyezetben az ilyen objektumokat agilisnak nevezzük. A Windows futtatókörnyezeti osztályok többsége agilis, de néhány osztály nem, és még az agilis osztályok is speciális kezelést igényelhetnek.
Ahol csak lehetséges, a közös nyelvi futtatókörnyezet (CLR) úgy kezeli a más forrásokból származó objektumokat, mint például a Windows futtatókörnyezetet, mintha .NET-keretrendszer-objektumok lennének:
Ha az objektum implementálja az IAgileObject interfészt, vagy a MarshalingBehaviorAttribute attribútummal rendelkezik a MarshalingType.Agile használatával, a CLR agilisként kezeli.
Ha a CLR képes egy hívás átirányítására arról a szálról, amelyen az eredetileg történt, a célobjektum szálkezelési környezetébe, akkor ezt átlátható módon végzi.
Ha az objektum MarshalingBehaviorAttribute attribútummal rendelkezik a MarshalingType.None tulajdonsággal, az osztály nem ad meg marsallálási információkat. A CLR nem tudja kezdeményezni a hívást, ezért érvénytelenCastException kivételt jelez, amely azt jelzi, hogy az objektum csak abban a szálkezelési környezetben használható, ahol létrejött.
A következő szakaszok a viselkedés különböző forrásokból származó objektumokra gyakorolt hatását ismertetik.
C# vagy Visual Basic nyelven írt Windows Runtime-összetevő objektumai
Az összetevő összes aktiválható típusa alapértelmezés szerint agilis.
Megjegyzés:
Az agilitás nem jelenti a szál biztonságát. A Windows futtatókörnyezetben és a .NET-keretrendszerben a legtöbb osztály nem biztonságos a szálbiztonsággal, mert a szálbiztonság teljesítményköltséggel jár, és a legtöbb objektumhoz soha nem fér hozzá több szál. Hatékonyabb az egyes objektumokhoz való hozzáférés szinkronizálása (vagy a szálbiztos osztályok használata) csak szükség esetén.
Windows futtatókörnyezeti összetevő létrehozásakor felülbírálhatja az alapértelmezett értéket. Lásd az ICustomQueryInterface felületet és az IAgileObject felületet.
Objektumok a Windows futtatókörnyezetből
A Windows Futtatókörnyezet legtöbb osztálya agilis, a CLR pedig agilisként kezeli őket. Az osztályok dokumentációja a "MarshalingBehaviorAttribute(Agile)" értéket sorolja fel az osztályattribútumok között. Néhány ilyen agilis osztály, például az XAML-vezérlők tagjai azonban kivételeket vetnek ki, ha nem hívják meg őket a felhasználói felületi szálon. Az alábbi kód például egy háttérszál használatával próbálja beállítani a kattintott gomb tulajdonságát. A gomb Content tulajdonsága kivételt eredményez.
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
A gombot biztonságosan érheti el a Dispatcher tulajdonságával, vagy a Dispatcher felhasználói felületi szál környezetében található objektumok tulajdonságával (például azon az oldalon, amelyen a gomb található). Az alábbi kód a CoreDispatcher objektum RunAsync metódusával küldi el a hívást a felhasználói felületen.
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
Megjegyzés:
A Dispatcher tulajdonság nem okoz kivételt, ha egy másik szálról hívják.
A felhasználói felületen létrehozott Windows Futtatókörnyezet objektum élettartamát a szál élettartama határozza meg. Az ablak bezárása után ne próbáljon meg hozzáférni egy felhasználói felületi szál objektumaihoz.
Ha saját vezérlőt hoz létre egy XAML-vezérlő öröklésével vagy XAML-vezérlők megírásával, akkor a vezérlő agilis, mert .NET-keretrendszer-objektum. Ha azonban meghívja az alaposztály vagy az azt alkotó osztályok tagjait, vagy ha öröklött tagokat hív meg, ezek a tagok kivételeket fognak kivenni, ha a felhasználói felületi szál kivételével bármely szálról meghívják őket.
Olyan osztályok, amelyek nem hajthatóak be
Azok a Windows futtatókörnyezeti osztályok, amelyek nem adnak meg marshaling információt, az MarshalingBehaviorAttribute attribútummal rendelkeznek MarshalingType.None. Az ilyen osztály dokumentációja a "MarshalingBehaviorAttribute(None)" értéket sorolja fel attribútumai között.
Az alábbi kód létrehoz egy CameraCaptureUI objektumot a felhasználói felület szálán, majd megpróbálja beállítani az objektum tulajdonságát egy szálkészlet száláról. A CLR nem tudja végrehajtani a hívást, és System.InvalidCastException kivételt küld egy üzenettel, amely azt jelzi, hogy az objektum csak abban a szálkezelési környezetben használható, ahol létrejött.
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
A CameraCaptureUI dokumentációja a "ThreadingAttribute(STA)" értéket is felsorolja az osztály attribútumai között, mivel egyszálas környezetben kell létrehozni, például a felhasználói felületi szálon.
Ha egy másik szálról szeretné elérni a CameraCaptureUI objektumot, gyorsítótárba helyezheti a CoreDispatcher objektumot a felhasználói felület szálához, és később felhasználhatja a hívás elküldéséhez. Vagy beszerezheti a diszpécsert egy XAML-objektumból, például a lapról, ahogy az az alábbi kódban is látható.
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
A C++ nyelven írt Windows Futtatókörnyezet összetevő objektumai
Alapértelmezés szerint az aktiválható összetevő osztályai agilisak. A C++ azonban jelentős mértékű vezérlést tesz lehetővé a szálmodellek és az őrlési viselkedés felett. A cikk korábbi részében leírtak szerint a CLR felismeri az agilis osztályokat, megkísérli az együttműködés megszervezését, amikor az osztályok nem agilisak, és dob egy System.InvalidCastException kivételt, ha egy osztály nem rendelkezik marshaling információval.
A felhasználói felületi szálon futó objektumok, amelyek hibát okoznak, ha nem a felhasználói felületi szálhoz tartozó szálról hívják meg őket, a hívást elirányíthatja a felhasználói felületi szál CoreDispatcher objektumának használatával.