3

既存のアプリケーションを修正していますが、いくつかの奇妙な問題で立ち往生しています。

GUI の一部で、時間がかかる操作がありました。そこでWait、簡単なメッセージPlease wait...を名前に付けた小さなウィンドウを作成しました。Show/Hideそして、必要なときにウィンドウを単純にします。

しかし、ここに問題があります。2 回目にウィンドウを表示すると、Please wait... Labelin は表示されません。

Wait.xaml:

<Window x:Class="WpfApplication1.Wait"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Wait" SizeToContent="WidthAndHeight">
    <StackPanel>
        <Label>Please wait...</Label>
    </StackPanel>
</Window>

Wait.xaml.cs

public partial class Wait : Window
{
    public Wait()
    {
        InitializeComponent();
    }
}

最後に、最小限の WPF アプリケーションでこれを試してみます。

// The window is shown perfectly
m_WaitWindow.Show();
Thread.Sleep(5000);
m_WaitWindow.Hide();

Thread.Sleep(2000);

// The label is not shown, the window is empty
m_WaitWindow.Show();
Thread.Sleep(5000);
m_WaitWindow.Hide();

この問題を解決する方法がわかりません。UpdateLayoutその後のように多くのことを試しましたShowが、効果はありませんでした。

これを解決する方法についての答え以上に、なぜこれが起こっているのかを理解したいですか?

4

2 に答える 2

0

Hans Passant が言ったように、UI スレッドをブロックしています。(Dr. Seuss のように答えるつもりはありません...)

これは、バックグラウンド スレッドで待機/重い作業を行うことで、かなり簡単に修正されます。最終的な実装は、使用している .NET と Visual Studio のバージョンによって異なりますが、次の簡単な例を使用して目的を達成できます。

// The window is shown perfectly.
m_WaitWindow.Show();
ThreadPool.QueueUserWorkItem(arg =>
    {
        Thread.Sleep(5000);
        Dispatcher.BeginInvoke(new Action(() => m_WaitWindow.Hide()));

        Thread.Sleep(2000);

        // The window is still shown perfectly, because the UI thread is not being blocked.
        Dispatcher.BeginInvoke(new Action(() => m_WaitWindow.Show()));
        Thread.Sleep(5000);
        Dispatcher.BeginInvoke(new Action(() => m_WaitWindow.Hide()));
    }, null);

注: 元のケースでは、ポップアップ ウィンドウがユーザーの操作に応答していないこともわかるはずです。これは、UI スレッドがブロックされていることを示す良い兆候です。

于 2013-09-12T18:09:54.513 に答える