2012-03-06 14 views
5

Tôi có một BindingList không đồng bộ có chứa các đối tượng được thao tác trên một chuỗi công nhân và bị ràng buộc vào một BindingSource trên luồng giao diện người dùng chính với một BindingSource ràng buộc với một DataGridView.Định vị các đối tượng trong BindingList

Có thể nào định vị các đối tượng trong BindingList của tôi mà không cần lặp qua danh sách không?

Tôi đã xem xét kỹ hơn LINQ và về cơ bản nó là một vòng lặp foreach tráng đường. Ngoài ra từ hiểu của tôi nếu tôi thực hiện IBindingList.Find() nó không có gì nhiều hơn một for-loop ...

Tôi đã "cố gắng" để đồng bộ hóa/bản đồ BindingList của tôi vào một từ điển gương BindingList của tôi và sử dụng từ điển để định vị các đối tượng và chuyển các kết quả (index) tới BindingList của tôi nhưng điều này không hoạt động vì chỉ có quá nhiều việc thêm và loại bỏ các đối tượng và tôi không thể giữ mọi thứ được tổ chức.

Đây là ứng dụng hiệu suất cao xử lý dữ liệu tần số cao thời gian thực từ thị trường chứng khoán. Đó là lý do tại sao tôi không thể lặp qua BindingList, nó chỉ là không hiệu quả.

Ai đó có thể vui lòng cho tôi một số lời khuyên và/hoặc giải pháp.

Trả lời

5

Vì vậy, một số loại danh sách ràng buộc tra cứu nhanh ... Đây là một trong những điều tôi đã chuẩn bị trước đó.

Đây là phương pháp 'đồng bộ hóa/bản đồ' mà bạn đã đề cập đến. Tôi đã sử dụng điều này trước đây để có dữ liệu đánh dấu nhanh, nơi nút cổ chai chính đang tìm kiếm các mục trong danh sách. Tôi tin rằng tôi đã đề cập đến tất cả các phương pháp cần thiết để giữ đồng bộ hóa hoặc 'được tổ chức'. Bạn có thể thêm một thử nghiệm cho AddRange - Tôi không có một trình biên dịch ngược để bàn tay, tôi không chắc chắn nếu nó chỉ gọi InsertItem. Rõ ràng là bạn có một sự cân bằng trực tiếp ở đây sử dụng bộ nhớ lớn hơn và thời gian chèn, duy trì hai danh sách, nhưng đối với dữ liệu đánh dấu nhanh, đó là một thương mại rất chấp nhận được để cải thiện thời gian tra cứu.

Sử dụng lớp như bạn sẽ là BindingList, nhưng khi bạn cần tra cứu một mục nhanh chóng, hãy sử dụng phương pháp 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(); 
    } 
} 

Cách sử dụng:

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); 
    } 
+0

thx stevenP! tôi chưa bao giờ thấy giải pháp của bạn. Tôi sẽ thực hiện điều này bây giờ ans xem cách nó hoạt động. nó trông tốt mặc dù và đây là những gì tôi đã cố gắng để trước nhưng không thể có được sự đồng bộ tại chỗ –

+0

Làm thế nào bạn sẽ làm cho threadafe này. Chúng tôi có cùng một trường hợp sử dụng trong đó một backgroundthread cập nhật danh sách liên kết được lập chỉ mục. Tuy nhiên, việc sử dụng triển khai của bạn sẽ gây ra sự cố đồng bộ hóa. Thêm khóa ở khắp mọi nơi, cũng làm tổn thương hiệu suất. – Rik

+0

Bạn có thể sử dụng ISynchronizeInvoke.Invoke để thực hiện các cập nhật của mình không? Tức là, hãy sử dụng nhân viên nền để thực hiện nhiệm vụ truy xuất/xử lý dữ liệu của bạn trong thời gian dài, sau đó khi nó sẵn sàng, hãy gọi Invoke để nhận chủ đề UI và cập nhật BindingList? –