dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
7.01k stars 1.16k forks source link

Remote Deskop Disconnect/Reconnect Issues #6739

Open Krudonix opened 2 years ago

Krudonix commented 2 years ago

Not sure if question/defect.

I've done alot of googling found some responses, but nothing that ultimately helps.

When reconnecting to a remote desktop session we are seeing the following.

Is there anyway to prevent this from happening ?

We have ported a very large Silverlight application to WPF and this is biting us pretty hard.

In some cases we been able to refactor some logic to reduce the number of usages of loaded/unloaded events.

But we also have alot of Behaviors, Converters, etc breaking within a DataTemplate.

We making very slow progress here, and hoping to find a more of a global solution to prevent this from occurring.

If you can please assist.

Many thanks

Minimal repro:

With the below reconnect to disconnected remote desktop session.

Notice the Unloaded then Loaded callback hits. Notice the hashcode for the TextBlock has changed.


     <Grid.Resources>
            <local:HashCodeConverter x:Key="hashcodeconverter" />
            <DataTemplate x:Key="datatemplate">
                <TextBlock x:Name="txtblock"
                           Text="{Binding ElementName=txtblock, Converter={StaticResource hashcodeconverter}}" />
            </DataTemplate>
        </Grid.Resources>

        <StackPanel>
            <ContentControl ContentTemplate="{StaticResource datatemplate}" />
            <Button Loaded="Button_Loaded"
                    Unloaded="Button_UNLoaded">Test</Button>
        </StackPanel>
Krudonix commented 1 year ago

Hi,

There perhaps any advice that can be given here ?

Many thanks, Daniel

butterworld commented 10 months ago

Also curious about this. I've seen some mentions of people dealing with this in the Loaded event handler, but for me the first breakpoint that gets hit is in the constructor and I don't know how to debug it further because the stack trace only shows [external code] before this.

Krudonix commented 9 months ago

Anyway to escalate this issue ?

We are hitting this issue more and more.

We even starting to see same/similar issues when users with several screens connected to their laptops close and open their laptop lid.

lindexi commented 8 months ago

@Krudonix We can use the Hardware Acceleration in rdp in dotnet 8. And could you try enable the Hardware Acceleration in rdp? I'm not sure I can help with that.

Dhruv0201Tatvasoft commented 2 months ago

Hey , We are having the same issue in our WPF application we are using .NETFramework version 4.6 have you find any solution for the issue???

lindexi commented 2 months ago

@Dhruv0201Tatvasoft Could you try to write the wpf demo application with dotnet 8 and try enable the Hardware Acceleration in rdp? If it turns out that enable the Hardware Acceleration can be solved, then we can talk about how to delegate this feature to the older version.

Dhruv0201Tatvasoft commented 2 months ago

Thanks for the reply but how do i turn on the hardware Acceleration in here they say enable from runtimeconfig.json but i could not find it in my build or anywhere else would you please tell how can i enable it if you know?

Dhruv0201Tatvasoft commented 2 months ago

@lindexi i am trying to add

<ItemGroup>
    <RuntimeHostConfigurationOption Include="Switch.System.Windows.Media.EnableHardwareAccelerationInRdp" Value="true" />
  </ItemGroup>

in my app.config file and i'll let you know it it works.

lindexi commented 2 months ago

@Dhruv0201Tatvasoft You can set it on your app ctor:

        public App()
        {
            AppContext.SetSwitch("Switch.System.Windows.Media.EnableHardwareAccelerationInRdp", true);
        }
Dhruv0201Tatvasoft commented 2 months ago

@lindexi i have tried both unfortunately none of them works.

lindexi commented 2 months ago

@Dhruv0201Tatvasoft What is none of them works means? Could you describe the phenomenon? I'm worried that even turning on hardware rendering won't solve the problem.

Dhruv0201Tatvasoft commented 2 months ago

i tired to add this setting in app.config file , tried to do as you said and tried to do change env variable like said in this article. the loaded and unloaded method getting called again.

Dhruv0201Tatvasoft commented 1 month ago

Hey @lindexi i have made some tweaks to prevent the issue. however this is not a straight forward solution but kind of a trick to get the desired the output.

in my mainwindow.xaml.cs

private bool IsDisconnect = false; // flag to check whether session is disconnected or not.
private int counter;// to check the number of controls that are getting loaded or unloaded 

public MainWindow()
{
    SystemEvents.SessionSwitch += new SessionSwitchEventHandler(SystemEvents_SessionSwitch);
    EventManager.RegisterClassHandler(typeof(UserControl), UserControl.LoadedEvent, new RoutedEventHandler(UserControlLoaderUnloaderHandler));
    EventManager.RegisterClassHandler(typeof(UserControl), UserControl.UnloadedEvent, new RoutedEventHandler(UserControlLoaderUnloaderHandler));
    EventManager.RegisterClassHandler(typeof(Page), Page.LoadedEvent, new RoutedEventHandler(PageLoaderUnLoaderHandler));
    EventManager.RegisterClassHandler(typeof(Page), Page.UnloadedEvent, new RoutedEventHandler(PageLoaderUnLoaderHandler));
     //rest of the code
}

private void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
        {
            if (e.Reason == SessionSwitchReason.) IsDisconnect = true;
        }

private void UserControlLoaderUnloaderHandler(object sender, RoutedEventArgs e)
        {
            var userControl = sender as UserControl;
            if (userControl != null && IsDisconnect)
            {
                e.Handled = true;
                if (e.RoutedEvent == FrameworkElement.UnloadedEvent) counter++;
                if (e.RoutedEvent == FrameworkElement.LoadedEvent) counter--;
            }
            if (IsDisconnect && counter == 0) IsDisconnect = false;
        }

        private void PageLoaderUnLoaderHandler(object sender, RoutedEventArgs e)
        {
            var page = sender as Page;
            if (page != null && IsDisconnect)
            {
                e.Handled = true;
                if (e.RoutedEvent == FrameworkElement.UnloadedEvent) counter++;
                if (e.RoutedEvent == FrameworkElement.LoadedEvent) counter--;
            }
            if (IsDisconnect && counter == 0) IsDisconnect = false;
        }

i set the flag IsDisconnect to true when the session switch cause is RemoteDisconnect. and every time the ammount of Ucs or Pages are getting unloaded the same ammount of Ucs and Pages are getting loaded too so using the counter we can increase it when it unloads and we can decrease when it loads again now whenever it hits to zero and our flag is true we make the flag to false. now making it false it wont go inside first if condition and e.Handled will not be true so the method which is subscribed inside the UC or Page 's xaml.cs will be called and we'll get the desired output afterwards.

lindexi commented 1 month ago

This is a troubling problem...