IComparer接口是否在C#中的单独线程上工作?

时间:2012-01-24 22:02:48

标签: c# listview sorting thread-safety

我正在使用实现IComparer接口的通用ListView排序器。

这是否与主线程分开?

我有一些时髦的结果。它对静态ListView进行排序就好了,但是,一旦它填充了流数据(它订阅了一些不断添加项目的事件),比较失败就变得很时髦了。

如果它在一个单独的线程上 - 有关如何修改它的任何想法,以便它不会干扰填充结果(反之亦然)?

或者,如果它出现在相同的主题上,那么为什么会出现这种情况?

以下是更新listView(lstTrades

的更新方法的代码 编辑:我原本错误地编写了错误的代码!!

  private void UpdateList(foo t)
                {
                lstTrades.Items.Add(t.a);
                int i = lstTrades.Items.Count - 1;
                lstTrades.Items[i].SubItems.Add(t.b);
                lstTrades.Items[i].SubItems.Add(t.c.ToString());
                lstTrades.Items[i].SubItems.Add(t.d.ToString());
                lstTrades.Items[i].SubItems.Add(Math.Round(e.pnl, 2).ToString());
                lstTrades.Items[i].SubItems.Add(t.f.ToString());
                lstTrades.Items[i].SubItems.Add(t.g.ToShortTimeString());
                lstTrades.Items[i].SubItems.Add(t.h);
                lstTrades.Items[i].SubItems.Add(t.i.ToString());
                }

排序代码是来自http://support.microsoft.com/kb/319401

的温和修改代码
using System.Collections;
using System.Windows.Forms;
using System;


namespace Aladmin2
{


/// <summary>
/// This class is an implementation of the 'IComparer' interface.
/// </summary>
public class ListViewColumnSorter : IComparer
{
    /// <summary>
    /// Specifies the column to be sorted
    /// </summary>
    private int ColumnToSort;
    /// <summary>
    /// Specifies the order in which to sort (i.e. 'Ascending').
    /// </summary>
    private SortOrder OrderOfSort;
    /// <summary>
    /// Case insensitive comparer object
    /// </summary>
    private CaseInsensitiveComparer ObjectCompare;

    /// <summary>
    /// Class constructor.  Initializes various elements
    /// </summary>
    public ListViewColumnSorter()
    {
        // Initialize the column to '0'
        ColumnToSort = 0;

        // Initialize the sort order to 'none'
        OrderOfSort = SortOrder.None;

        // Initialize the CaseInsensitiveComparer object
        ObjectCompare = new CaseInsensitiveComparer();
    }

    /// <summary>
    /// This method is inherited from the IComparer interface.  It compares the two objects passed using a case insensitive comparison.
    /// </summary>
    /// <param name="x">First object to be compared</param>
    /// <param name="y">Second object to be compared</param>
    /// <returns>The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'</returns>
    public int Compare(object x, object y)
    {
        int compareResult;
        ListViewItem listviewX, listviewY;

        // Cast the objects to be compared to ListViewItem objects
        listviewX = (ListViewItem)x;
        listviewY = (ListViewItem)y;

        // Compare the two items
        DateTime dateValue;
        if (DateTime.TryParse(listviewX.SubItems[ColumnToSort].Text, out  dateValue))
        {

            compareResult = DateTime.Compare(DateTime.Parse(listviewX.SubItems[ColumnToSort].Text), DateTime.Parse(listviewY.SubItems[ColumnToSort].Text));

        }
        else
        {

            compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);
        }

        // Calculate correct return value based on object comparison
        if (OrderOfSort == SortOrder.Ascending)
        {
            // Ascending sort is selected, return normal result of compare operation
            return compareResult;
        }
        else if (OrderOfSort == SortOrder.Descending)
        {
            // Descending sort is selected, return negative result of compare operation
            return (-compareResult);
        }
        else
        {
            // Return '0' to indicate they are equal
            return 0;
        }
    }

    /// <summary>
    /// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
    /// </summary>
    public int SortColumn
    {
        set
        {
            ColumnToSort = value;
        }
        get
        {
            return ColumnToSort;
        }
    }

    /// <summary>
    /// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
    /// </summary>
    public SortOrder Order
    {
        set
        {
            OrderOfSort = value;
        }
        get
        {
            return OrderOfSort;
        }
    }

}

}

编辑:

我只在更新和排序中使用1个线程(我知道/创建)

3 个答案:

答案 0 :(得分:1)

编辑:在你提到的文章中,他们有一行:

this.listView1.Sort();

尝试在最后添加到ProcessUpdate方法。

此分拣机未实现连续排序 - 您需要在添加和删除数据时继续进行调用。对不起,我们都跳过了关于穿线的事。

编辑#2:另外,请尝试使用ProcessUpdate方法:

private void UpdateList(foo t)
{
    // Create the item
    ListViewItem li = new ListViewItem(t.a);

    // Add all of the subitems
    li.SubItems.Add(t.b);
    li.SubItems.Add(t.c.ToString());
    li.SubItems.Add(t.d.ToString());
    li.SubItems.Add(Math.Round(e.pnl, 2).ToString());
    li.SubItems.Add(t.f.ToString());
    li.SubItems.Add(t.g.ToShortTimeString());
    li.SubItems.Add(t.h);
    li.SubItems.Add(t.i.ToString());

    // Add the item to the list
    lstTrades.Items.Add(li);

    // Sort the list
    lstTrades.Sort();
}
<德尔> 如果您还没有,则需要将“ProcessUpdate”方法(以及触及绑定列表的任何其他内容)封送到UI线程。您无法安全地从后台线程更新这些内容,原因与您无法从后台线程触摸UI控件的原因相同。 但不,比较器没有在它自己的线程上运行。

答案 1 :(得分:0)

不能从多个线程使用这是不安全的。 ListViewItem实例本身并不能从多个线程中找不到,因此它在IComparer中的使用也是不安全的。

答案 2 :(得分:0)

不 - 它不在一个单独的线程上。 接口实际上并不代表任何可执行代码 - 只是类之间的契约。所以问题是你如何调用排序请求和什么集合实现。内置的集合类(List&lt;&gt;,ArrayList等)都没有使用单独的线程进行排序。

可能在单独的线程上的是您的事件通知。如果您在一个线程上修改列表并在另一个线程上对其进行排序,则会产生意外结果。