3

INotifyPropertyChangedを実装し、3つのプロパティ(1つのint、1つの文字列、および1つのbool)を持つカスタムオブジェクト(MyObject)があります。そのオブジェクトのコードは次のとおりです。

public class MyObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, e);
        }
    }

    private int _Index;
    public int Index
    {
        get { return _Index; }
        set
        {
            if (_Index == value)
            {
                return;
            }

            _Index = value;
            OnPropertyChanged(new PropertyChangedEventArgs("Index"));
        }
    }

    private string _Name;
    public string Name
    {
        get { return _Name; }
        set
        {
            if (_Name == value)
            {
                return;
            }

            _Name = value;
            _Modified = true;
            OnPropertyChanged(new PropertyChangedEventArgs("Name"));
        }
    }

    private bool _Modified;
    public bool Modified
    {
        get { return _Modified; }
        set
        {
            if (_Modified == value)
            {
                return;
            }

            _Modified = value;
            OnPropertyChanged(new PropertyChangedEventArgs("Modified"));
        }
    }

    public MyObject()
    {
    }

    public MyObject(int index, string number, bool modified)
    {
        Index = index;
        Number = number;
        Modified = modified;
    }
}

簡単に言うと、これらのオブジェクトのBindingListを次のようにDataGridViewに接続しています。

BindingList<MyObject> myObjectList = new BindingList<MyObject>();
BindingSource bindingSourceForMyObjects = new BindingSource();

bindingSourceForMyObjects.DataSource = myObjectList;
dataGridViewMyObjects.DataSource = bindingSourceForMyObjects;

アプリケーションを実行すると、myObjectListに100,000個のオブジェクト(ファイルから読み取ったもの)が入力され、DataGridViewに表示されます。DataGridViewには、オブジェクトの文字列プロパティを表示する列が1つしかありません。ユーザーがDataGridViewのすべての行を選択して、それらを「削除」したい場合があります。オブジェクトが実際に削除されるのではなく、100,000個すべてのオブジェクトの文字列プロパティがstring.Emptyに設定されるため、削除という用語の前後に引用符を使用します。今、私はこのコードを使用してその操作を実行します:

myObjectList.ToList().ForEach(c => c.Name = string.Empty);

この操作は、完了するまでに約55秒かかります。私も試しました:

foreach (DataGridViewRow row in dataGridViewMyObjects.SelectedRows)
{
    row.Cells["NAME"].Value = string.Empty;
}

これには49秒と少し時間がかかりますが、それでも長い操作です。ちなみに、私は次のようにbindingSourceForMyObjects用に定義されたListChangedイベントハンドラーも持っています。

private void bindingSourceForMyObjects_ListChanged(object sender, ListChangedEventArgs e)
{
    if (e.ListChangedType == ListChangedType.ItemChanged)
    {
        dataGridViewMyObjects.Rows[e.NewIndex].DefaultCellStyle.BackColor = Color.Red;
        dataGridViewMyObjects.Rows[e.NewIndex].DefaultCellStyle.ForeColor = Color.White;
    }
}

ご覧のとおり、これを使用して、基になるオブジェクトのリストにプログラムで変更を加えたときに、DataGridViewで変更された行を視覚的に示しています(すべてをstring.Emptyに設定した場合と同じです)。これにより、すべてのオブジェクトを「削除」するときにオーバーヘッドが追加されますが、このイベントハンドラーがなくても、操作に時間がかかります。

最後に、私のWinFormsアプリケーションは現在シングルスレッドですが、そうするのが理にかなっているコードをマルチスレッド化することを計画しています。この操作はそのようなケースの1つかもしれませんが、私がその道を進む前に、この操作のパフォーマンスを向上させるために私が見逃している(または実行する必要のないことを実行している)何かがありますか?完了するのにほぼ1分かかりますか?それとも、100,000個のオブジェクトを処理するという性質だけですか?

4

2 に答える 2

3

@User685869拡張オブジェクトを投稿していただきありがとうございます。

いくつかの簡単なテスト例を実行した後、PropertyChangedイベントを発生させると速度が低下しているようです。それへの呼び出しを削除すると、私のPC上の100kレコードの操作が1〜2秒以内に完了します。

これは、イベントのハンドラーがない場合でも発生します。

必要に応じてインターフェースを実装したと思います。そうしない場合は、削除すると問題が解決します。

私が提案できる唯一の解決策は、booleantrueに設定できる変数を作成して、一括更新を実行しているときにイベントが発生しないようにし、後で通常に戻すことです。これの欠点は、もちろん、一括操作を実行するときに発生するイベントがないことです。

例えば ​​:-

MyObject

public boolean bulk = false;
public string Name
{
    get { return _Name; }
    set
    {
        if (_Name == value)
        {
            return;
        }

        _Name = value;
        _Modified = true;
        OnPropertyChanged(new PropertyChangedEventArgs("Name"));
    }
}

親コード

_bindingList.ToList().ForEach(c =>
    {
       c.bulk = true;
       c.Name = string.Empty;
       c.bulk = false;
    });
于 2013-01-23T17:44:51.193 に答える
1

これを試して:

dataGridView1.SuspendLayout();
        //do changes
        dataGridView1.ResumeLayout();
于 2013-01-23T16:41:03.977 に答える