Požadavky:
- Když v jednom okně provádím náročnější operaci, nesmí vytuhnout ostatní okna.
- Když dojede k pádu v jednom modulu tak potřebuji, aby ostatní moduly fungovali dál.
Jak jsem psal v předešlém článku, požadovaného výsledku dosáhneme vytvořením STA vlákna pro každé okno.
Když pak spustíme aplikaci, zjistíme, že každé okno funguje opravdu v nezávislém vlákně. Brzo si všimnete velmi nepříjemné vlastnosti takové aplikace - okna jsou opravdu na sobě nezávislá a fungují jako samostatné aplikace uvnitř vaší aplikace. Důsledkem toho vám program přestane správně fungovat při minimalizaci a opětovné maximalizaci. Po opětovné maximalizaci se vám zobrazí pouze okno hlavního vlákna. Ale kde jsou ty ostatní okna?
První myšlenka, která mě napadla bylo, nastavení vlastnosti Window.Owner. Tuto vlastnost bohužel z jiného vlákna nenastavíte, protože tímto vyvoláte kód v hlavním vlákně.
_window.Owner = Application.Current.MainWindow;
Dojde k výjímce:
The calling thread cannot access this object because a different thread owns it.
Dlouho jsem procházel nejrůznější fóra, až jsem objevil konstrukci, která tuto WPF chybku obejde.
string strFriendlyName = AppDomain.CurrentDomain.FriendlyName; Process[] pro = Process.GetProcessesByName(strFriendlyName.Substring(0, strFriendlyName.LastIndexOf('.'))); typeof(System.Windows.Window).InvokeMember("_ownerHandle", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField, null, _window, new object[] { pro[0].MainWindowHandle }); _window.Closed += new EventHandler(WindowClosed); _window.WindowStartupLocation = WindowStartupLocation.CenterOwner; _window.ShowDialog(); //System.Windows.Threading.Dispatcher.Run();
A můžeme si oddechnout, opravdu to funguje.
Odkaz na článek
1 komentář:
Poznámka: Nemusím procházet procesy. Stačí:
Process pr = Process.GetCurrentProcess();
typeof(System.Windows.Window).InvokeMember("_ownerHandle",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField,
null, _window, new object[] { pr.MainWindowHandle });
Okomentovat