【解決方法】フリーズせずにWPFのユーザーインターフェイスを非同期に変更する最良の方法は何ですか?


やあ、
私は Dispatcher プロパティを変更して UI を変更し、追加しました System.Threading.Thread.Sleep(3000)Dispatcher.Invoke フリーズしないようにブロックしますが、UI は 3 秒間フリーズしたままです。
まあ言ってみればDispatcher.Invoke 何らかの理由でブロックに 2 秒かかるため、UI をフリーズさせたくありません。
50ms ルール: 「実行に 50 ミリ秒以上かかる可能性がある」操作は非同期にする必要があります。

上記によると、フリーズせずにWPFのユーザーインターフェイスを変更する最良の方法は何ですか?

これらは私のC#コードです:

C#
private async void Add_Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    await Task.Run(() =>
    {
        OleDbCommand OleDbCommandInsert = null;
        MessageWindow MW = null;
        Dispatcher.Invoke(() =>
        {
            OleDbParameter Parameter = new OleDbParameter();
            Parameter.OleDbType = OleDbType.Binary;
            Parameter.ParameterName = "BookImage";
            Parameter.Value = ImageToBytes((BitmapImage)BookImage.Source);
            OleDbCommandInsert = new OleDbCommand("Insert Into BookInfo(BookName,Authors,Publisher,[ISBN-13],[ISBN-10],Category,PublicationDate,BookLanguage,Length,[Type],Translators,Narrators,DeweyDecimalClassification,UniversalDecimalClassification,LibraryOfCongressClassification,BookImage,Price) Values(@BookName,@Authors,@Publisher,@ISBN13,@ISBN10,@Category,@PublicationDate,@BookLanguage,@Length,@Type,@Translators,@Narrators,@DeweyDecimalClassification,@UniversalDecimalClassification,@LibraryOfCongressClassification,@BookImage,@Price)", OleDbConnect);
            OleDbCommandInsert.Parameters.AddWithValue("@BookName", BookName_TextBox.Text);
            OleDbCommandInsert.Parameters.AddWithValue("@Authors", Authors_TextBox.Text);
            OleDbCommandInsert.Parameters.AddWithValue("@Publisher", PublicationDate_TextBox.Text);
            OleDbCommandInsert.Parameters.AddWithValue("@ISBN13", ISBN13_TextBox.Text);
            OleDbCommandInsert.Parameters.AddWithValue("@ISBN10", ISBN10_TextBox.Text);
            OleDbCommandInsert.Parameters.AddWithValue("@Category", Category_ComboBox.Text);
            OleDbCommandInsert.Parameters.AddWithValue("@PublicationDate", PublicationDate_TextBox.Text);
            OleDbCommandInsert.Parameters.AddWithValue("@BookLanguage", Language_TextBox.Text);
            OleDbCommandInsert.Parameters.AddWithValue("@Length", ushort.Parse(Length_TextBox.Text));
            OleDbCommandInsert.Parameters.AddWithValue("@Type", Type_ComboBox.Text);
            OleDbCommandInsert.Parameters.AddWithValue("@Translators", Translators_TextBox.Text);
            OleDbCommandInsert.Parameters.AddWithValue("@Narrators", Narrators_TextBox.Text);
            OleDbCommandInsert.Parameters.AddWithValue("@DeweyDecimalClassification", DeweyDecimalClassification_TextBox.Text);
            OleDbCommandInsert.Parameters.AddWithValue("@UniversalDecimalClassification", UniversalDecimalClassification_TextBox.Text);
            OleDbCommandInsert.Parameters.AddWithValue("@LibraryOfCongressClassification", LibraryOfCongressClassification_TextBox.Text);
            OleDbCommandInsert.Parameters.Add(Parameter);
            OleDbCommandInsert.Parameters.AddWithValue("@Price", Price_TextBox.Text);
        });
        OleDbConnect.Open();
        OleDbCommandInsert.ExecuteScalar();
        OleDbConnect.Close();
        Dispatcher.Invoke(() =>
        {
            MW = new MessageWindow();
            System.Threading.Thread.Sleep(3000);
            MW.YesButton.Visibility = Visibility.Hidden;
            MW.NoButton.Visibility = Visibility.Hidden;
            MW.Image.Source = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Check.bin"));
            switch (App.EnumLanguage)
            {
                case AllLanguage.English:
                    MW.MessageTextBlock.Text = "Information added successfully";
                    MW.OKButton.Content = "OK";
                    break;
                default:
                    MW.MessageTextBlock.Text = "اطلاعات با موفقیت اضافه شد";
                    MW.OKButton.Content = "تایید";
                    break;
            }
            MW.Show();
        });
    });
}

次のツールを使用します。
• .NET フレームワーク 4.5
•WPF
•OLE DB
• Windows 7

お時間をいただきありがとうございます。
メリークリスマス

私が試したこと:

私の一般的なポイントは、 Dispatcher.Invoke UI の更新に直接関係のないコードを含めないでください。
しかし、時々コードを書かなければなりません Dispatcher.Invoke.

解決策 1

ディスパッチャーで SQL コマンドを実行するべきではありません。 Dispatcher.Invoke が行うことは、Dispatcher が実行されているスレッドに操作をマーシャリングすることです。したがって、ここで行っていることは、実際には「長時間実行」操作を Dispatcher に強制的に戻すことです。 実際に行う必要があるのは、結果を Dispatcher にマーシャリングすることだけです。

基本的に、UI にマーシャリングする必要があるビットを絞り込み、それらの操作には Dispatcher.Invoke のみを使用します。 したがって、それはコード サンプルのデータベースとは関係ありません。

解決策 2

この特定のケース用のアルゴリズムを作成しました。 わかりやすくするために、次のように説明しました。
クリックしてご覧ください

XAML
<Window x:Class="Ganj_Aseman.MessageWindow" x:Name="Message_Window"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:Ganj_Aseman"
            mc:Ignorable="d"
            Loaded="MessageWindow_Loaded" AllowsTransparency="True" Background="Transparent" FontSize="13" Height="228" RenderTransformOrigin="0.5,0.5" ResizeMode="NoResize" ShowInTaskbar="False" Width="430" WindowStartupLocation="CenterOwner" WindowStyle="None">
        <Window.RenderTransform>
            <TransformGroup>
                <RotateTransform/>
                <ScaleTransform/>
            </TransformGroup>
        </Window.RenderTransform>
        <Window.Resources>
            <Storyboard x:Key="CloseMessageWindow" Storyboard.TargetName="Message_Window" Completed="CloseMessageWindow_Completed">
                <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[0].Angle" Duration="0:0:7" To="360"/>
                <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[1].ScaleX" Duration="0:0:7" To="0"/>
                <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[1].ScaleY" Duration="0:0:7" To="0"/>
                <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:7.5" To="0"/>
            </Storyboard>
        </Window.Resources>
        <Grid>
            <Button Name="OKButton" GotFocus="OKButton_GotFocus" PreviewMouseLeftButtonDown="OKButton_PreviewMouseLeftButtonDown" Content="OK" HorizontalAlignment="Left" VerticalAlignment="Top" Height="34" Margin="177.5,180,0,0">
                <Button.Effect>
                    <DropShadowEffect BlurRadius="3" ShadowDepth="0.1" Direction="-90" Color="#e9f1cc"/>
                </Button.Effect>
                <Button.Triggers>
                    <EventTrigger RoutedEvent="PreviewMouseLeftButtonDown">
                        <BeginStoryboard Storyboard="{StaticResource CloseMessageWindow}"/>
                    </EventTrigger>
                </Button.Triggers>
            </Button>
        </Grid>
    </Window>

C#
private async void Add_Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                await Task.Run(() =>
                {
                    OleDbParameter Parameter = new OleDbParameter();
                    Parameter.OleDbType = OleDbType.Binary;
                    Parameter.ParameterName = "BookImage";
                    Dispatcher.Invoke(() =>
                    {
                        Parameter.Value = ImageToBytes((BitmapImage)BookImage.Source);
                    });
                    OleDbCommand OleDbCommandInsert = new OleDbCommand("Insert Into BookInfo(BookName,Authors,Publisher,[ISBN-13],[ISBN-10],Category,PublicationDate,BookLanguage,Length,[Type],Translators,Narrators,DeweyDecimalClassification,UniversalDecimalClassification,LibraryOfCongressClassification,BookImage,Price) Values(@BookName,@Authors,@Publisher,@ISBN13,@ISBN10,@Category,@PublicationDate,@BookLanguage,@Length,@Type,@Translators,@Narrators,@DeweyDecimalClassification,@UniversalDecimalClassification,@LibraryOfCongressClassification,@BookImage,@Price)", OleDbConnect);
                    Dispatcher.Invoke(() =>
                    {
                        OleDbCommandInsert.Parameters.AddWithValue("@BookName", BookName_TextBox.Text);
                        OleDbCommandInsert.Parameters.AddWithValue("@Authors", Authors_TextBox.Text);
                        OleDbCommandInsert.Parameters.AddWithValue("@Publisher", PublicationDate_TextBox.Text);
                        OleDbCommandInsert.Parameters.AddWithValue("@ISBN13", ISBN13_TextBox.Text);
                        OleDbCommandInsert.Parameters.AddWithValue("@ISBN10", ISBN10_TextBox.Text);
                        OleDbCommandInsert.Parameters.AddWithValue("@Category", Category_ComboBox.Text);
                        OleDbCommandInsert.Parameters.AddWithValue("@PublicationDate", PublicationDate_TextBox.Text);
                        OleDbCommandInsert.Parameters.AddWithValue("@BookLanguage", Language_TextBox.Text);
                        OleDbCommandInsert.Parameters.AddWithValue("@Length", ushort.Parse(Length_TextBox.Text));
                        OleDbCommandInsert.Parameters.AddWithValue("@Type", Type_ComboBox.Text);
                        OleDbCommandInsert.Parameters.AddWithValue("@Translators", Translators_TextBox.Text);
                        OleDbCommandInsert.Parameters.AddWithValue("@Narrators", Narrators_TextBox.Text);
                        OleDbCommandInsert.Parameters.AddWithValue("@DeweyDecimalClassification", DeweyDecimalClassification_TextBox.Text);
                        OleDbCommandInsert.Parameters.AddWithValue("@UniversalDecimalClassification", UniversalDecimalClassification_TextBox.Text);
                        OleDbCommandInsert.Parameters.AddWithValue("@LibraryOfCongressClassification", LibraryOfCongressClassification_TextBox.Text);
                        OleDbCommandInsert.Parameters.Add(Parameter);
                        OleDbCommandInsert.Parameters.AddWithValue("@Price", Price_TextBox.Text);
                    });
                    OleDbConnect.Open();
                    OleDbCommandInsert.ExecuteScalar();
                    OleDbConnect.Close();
                    Dispatcher.Invoke(() =>
                    {
                        MessageWindow MW = new MessageWindow();
                        MW.Owner = this;
                        MW.Owner.IsEnabled = false;
                        MW.YesButton.Visibility = Visibility.Hidden;
                        MW.NoButton.Visibility = Visibility.Hidden;
                        MW.Image.Source = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Check.bin"));
                        switch (App.EnumLanguage)
                        {
                            case AllLanguage.English:
                                MW.MessageTextBlock.Text = "Information added successfully";
                                MW.OKButton.Content = "OK";
                                break;
                            default:
                                MW.MessageTextBlock.Text = "اطلاعات با موفقیت اضافه شد";
                                MW.OKButton.Content = "تایید";
                                break;
                        }
                        MW.Show();
                    });
                });
            }

C#
private void OKButton_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.Owner.IsEnabled = true;
        }
        private void CloseMessageWindow_Completed(object sender, EventArgs e)
        {
            Close();
        }

結果(私は Duration のプロパティ Animation 結果をよりよく理解するために 7 秒まで):
クリックしてご覧ください

コメント

タイトルとURLをコピーしました