データ バインディングと非同期処理 (その 1)

WPF をはじめとする XAML UI テクノロジにおいて、
通信やストレージ I/O などの時間のかかる可能性のある処理を非同期で実行させる方法について考えます。
前提として、モデル層のデータはデータ バインディングによって UI 層に反映されるものとします。

 

まずは準備として、WPF アプリケーション プロジェクトを作成し、次のようなメソッドを作成します。
文字列を変換させるだけですが、疑似的に時間のかかるメソッドとするために 3 秒間ブロックさせています。

ConvertUtility.cs


public static class ConvertUtility
{
    // 処理に時間のかかるメソッド。
    public static string ToUpper(string text)
    {
        Thread.Sleep(3000);
        return text.ToUpper();
    } 
}


 

次に、モデルとなるクラスを作成します。
入力と出力を表すプロパティのみを定義します。

TextModel.cs


public class TextModel : INotifyPropertyChanged
{
    private string input;
    public string Input
    {
        get { return input; }
        set
        {
            if (input == value) return;
            input = value;
            NotifyPropertyChanged();
        }
    }

    private string output;
    public string Output
    {
        get { return output; }
        private set
        {
            if (output == value) return;
            output = value;
            NotifyPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = (o, e) => { };

    public void NotifyPropertyChanged([CallerMemberName]string propertyName = "")
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public void AddPropertyChangedHandler(string propertyName, Action action)
    {
        if (action == null) throw new ArgumentNullException("action");

        PropertyChanged += (o, e) =>
        {
            if (e.PropertyName == propertyName)
            {
                action();
            }
        };
    }

    public TextModel()
    {
        // Input プロパティの値が変更されたら、それを変換して Output プロパティに設定します。
        AddPropertyChangedHandler("Input", () => Output = ConvertUtility.ToUpper(Input));
    }
}


 

TextModel クラスのコンストラクターには、
Input プロパティの値が変更されたら、それを変換して Output プロパティに設定する、
というコードを追加しています。

最後に UI です。
Window の DataContext に TextModel オブジェクトを設定し、
上側の TextBox を Input に、下側の TextBlock を Output にそれぞれバインドします。

MainWindow.xaml

MainWindow.xaml

 

このアプリを実行してみると、起動は遅く、テキストを編集したときにフリーズしてしまいます。
実は、Visual Studio や Blend のデザイン画面上での編集中にも同様にフリーズします。

実行結果

これは、時間のかかる処理を UI スレッドで実行していることが原因です。
次回のデータ バインディングと非同期処理 (その 2) では、これを非同期処理に変更する方法について記述します。

 

バージョン情報
C# 5.0
.NET Framework 4.5

コメント / トラックバック2件 to “データ バインディングと非同期処理 (その 1)”

  1. データ バインディングと非同期処理 (その 2) | Do Design Space Says:

    […] 前回のデータ バインディングと非同期処理 (その 1) からの続きです。 […]

  2. Kinect アプリで UI スレッドへの負荷を軽減する | Do Design Space Says:

    […] 要素への値の反映については、 以前にデータ バインディングと非同期処理 (その 1) で書いた通り、データ […]


コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。