0

1 週間以上前から問題があり、その理由がわかりません。

私は別のスレッドに配置した待機中の画面を持っているので、コードが大量の作業を行っている場合でも、それを読み込んでそれ自体を表示できます (同じスレッドで evrything を実行すると、画面にそれが自己であることは表示されず、私はコードが他のことをするのに忙しかったからだと思います)

ただし、常に数回だけフリーズするとは限らず、タブレットでのみ、私のPCで正常に動作します(少なくとも、PCでテストしているときにフリーズしていることに気づきませんでした)。

いくつかの回避策を「ハック」しようとしました。たとえば、待機中の画面にキャンセル ボタンを配置して、閉じることはできますが、クリックすることはできません (フリーズして応答しないかのように)。

1回、スレッドが開始される前にスレッドを閉じるため、問題が発生していると思ったので、スレッドがまだロードされているかどうかを示すブール値を作成し、スレッドを閉じようとしたときに、スレッドの起動が完了するとイベント リスナーが閉じられるようにします。

とにかくここにコードがあります。ここの誰かが私を助けてくれることを願っています。

public partial class WaitWindow : Window
{
    //private static WaitWindow ww = new WaitWindow();
    private static Thread thread;
    private static event ThreadStartingEvent started;
    private delegate void ThreadStartingEvent(object sender, EventArgs e);
    public static bool disposable = false;

    private static bool startingThread;
    private static bool StartingThread
    {
        get
        {
            return startingThread;
        }
        set
        {
            startingThread = value;
            if (!startingThread && started != null)
            {
                started(null, new EventArgs());
            }
        }
    }

    // To refresh the UI immediately
    private delegate void RefreshDelegate();
    private static void Refresh(DependencyObject obj)
    {
        obj.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render,
            (RefreshDelegate)delegate { });
    }

    public WaitWindow()
    {
        InitializeComponent();
    }

    public static void BeginDisplay()
    {
        if (thread == null)
        {
            startingThread = true;
            thread = new Thread(() =>
            {
                WaitWindow ww = new WaitWindow();
                ww.Show();


                ww.Closed += (sender2, e2) =>
                ww.Dispatcher.InvokeShutdown();
                System.Windows.Threading.Dispatcher.Run();
            });
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
            startingThread = false;
        }
    }

    public static void EndDisplay()
    {
        if (startingThread)
        {
            started += new ThreadStartingEvent(WaitWindow_started);
        }
        if (thread != null)
        {
            disposable = false;
            thread.Abort();
            thread = null;
        }
    }

    static void WaitWindow_started(object sender, EventArgs e)
    {
        thread.Abort();
        thread = null;
        started = null;
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        if (disposable)
        {
            disposable = false;
            thread.Abort();
            thread = null;
        }
    }
}

および xaml コード:

<Window x:Class="WpfApplication1.WaitWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
    Title="WaitWindow" WindowStyle="None" ResizeMode="NoResize" WindowStartupLocation="CenterScreen"
    Background="Transparent" AllowsTransparency="True" 
        Width="1024" Height="640">
    <Grid>
        <xctk:BusyIndicator Name="BusyBar" IsBusy="True" BusyContent="Even geduld a.u.b.">
        </xctk:BusyIndicator>
        <Button Name="button1" Width="28" HorizontalAlignment="Left" Margin="550,271,0,0" Height="28" VerticalAlignment="Top" Click="button1_Click">X</Button>
    </Grid>
</Window>

おそらくいくつかの追加情報:時間がかかる可能性のあるタスクを実行している場合(リモートデータベースからデータを取得する場合)に電話BeginDisplay()し、コードが完了したら電話しますEndDisplay() これはかなり明白に思えましたが、言及しても害はないと思います.

編集:私はおそらく.net Framework 3.5を使用していることに言及する必要があります

4

2 に答える 2

0

通常、UI をロックしている処理をバックグラウンド スレッドに移動し、 によって返されるすべての UI 更新に対してメイン スレッドを解放したままにするため、Dispatcher.Invoke()ここにあるのは非常に異なる実装です。

私が最初に飛び出すのはThread.Abort()、スレッドを停止する他の手段がない限り、MSDNのドキュメントに基本的に使用しないでくださいと書かれていることです。特に、スレッドを中止した場合、開いているウィンドウを閉じるために何が残されますか。これはあなたの問題でしょうか?

于 2013-10-17T06:44:22.093 に答える
0

バックグラウンドで非同期タスクを実行している場合は、SynchronizationContext を作成する必要があります。おそらくこれが問題の原因ですか?

// Create a thread
Thread newWindowThread = new Thread(new ThreadStart( () =>
{
    // Create our context, and install it:
    SynchronizationContext.SetSynchronizationContext(
        new DispatcherSynchronizationContext(
            Dispatcher.CurrentDispatcher));

    Window1 tempWindow = new Window1();
    // When the window closes, shut down the dispatcher
    tempWindow.Closed += (s,e) => 
       Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);

    tempWindow.Show();
    // Start the Dispatcher Processing
    System.Windows.Threading.Dispatcher.Run();
}));

// Set the apartment state
newWindowThread.SetApartmentState(ApartmentState.STA);
// Make the thread a background thread
newWindowThread.IsBackground = true;
// Start the thread
newWindowThread.Start();

このコードは、よく読む価値のあるこのブログ記事から抜粋したものです。

于 2013-10-17T06:41:27.610 に答える