なので、ある種の高速検索バインディングリスト...これは私が先に準備したものです。
これはあなたが参照した「同期/マップ」アプローチです。私は、主なボトルネックがリスト内の項目を検索していたデータを高速にチェックするためにこれを使用しました。私は、同期しているか「組織化」しておく必要があるすべての方法をカバーしてきたと信じています。あなたはAddRangeのテストを追加するかもしれません - 私はデコンパイラを手にする必要はありません、私はそれが単にInsertItemを呼び出すかわかりません。
明らかに、メモリ使用量と挿入時間を増やすことで、2つのリストを維持することができますが、速くデータをチェックするためには、通常、ルックアップ時間を大幅に短縮できます。
BindingList
のようにクラスを使用しますが、アイテムをすばやく検索する必要がある場合は、FastFindメソッドを使用します。
public class FastLookupBindingList<TKey, TVal> : BindingList<TVal>
{
private readonly IDictionary<TKey, TVal> _dict = new Dictionary<TKey, TVal>();
private readonly Func<TVal, TKey> _keyFunc;
public FastLookupBindingList(Func<TVal, TKey> keyFunc)
{
_keyFunc = keyFunc;
}
public FastLookupBindingList(Func<TVal, TKey> keyFunc, IList<TVal> sourceList) : base(sourceList)
{
_keyFunc = keyFunc;
foreach (var item in sourceList)
{
var key = _keyFunc(item);
_dict.Add(key, item);
}
}
public TVal FastFind(TKey key)
{
TVal val;
_dict.TryGetValue(key, out val);
return val;
}
protected override void InsertItem(int index, TVal val)
{
_dict.Add(_keyFunc(val), val);
base.InsertItem(index, val);
}
protected override void SetItem(int index, TVal val)
{
var key = _keyFunc(val);
_dict[key] = val;
base.SetItem(index, val);
}
protected override void RemoveItem(int index)
{
var item = this[index];
var key = _keyFunc(item);
_dict.Remove(key);
base.RemoveItem(index);
}
protected override void ClearItems()
{
_dict.Clear();
base.ClearItems();
}
}
使用法:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
private void simpleButton1_Click(object sender, EventArgs e)
{
var keyedBindingList = new FastLookupBindingList<int, Person>(p => p.Id)
{
new Person {Id = 1, Name = "Joe"},
new Person {Id = 2, Name = "Josephine"}
};
var person = keyedBindingList.FastFind(2);
var unkonwn = keyedBindingList.FastFind(4);
}
THX stevenP!私はあなたの解決策を見たことがなかった。私はこれを実装しようとしています。それは良い見えて、これは私が以前にしようとしていたが、場所に同期を得ることができなかった –
どのようにこのスレッドセーフを行いますか。 backgroundthreadがインデックス付きバインディングリストを更新するのと同じユースケースがあります。ただし、実装を使用すると、同期の問題が発生します。あらゆる場所でロックを追加すると、パフォーマンスも低下します。 – Rik
ISynchronizeInvoke.Invokeを使用して更新を行うことはできますか?つまり、バックグラウンドワーカーを使用してデータの取得/操作の長期実行タスクを実行し、準備ができたらInvokeを呼び出してUIスレッドを取得し、BindingListを更新します。 –