簡體   English   中英

嘗試使用內置的.Sort()方法對ListView WinForms C#進行排序時,程序掛起(僅影響Visual Studio)

[英]Program hangs while trying to sort ListView WinForms C# using builtin .Sort() method (only Visual Studio is affected)

我在ListView遇到一個奇怪的問題,該問題拒絕對其進行正確排序。 我在程序中99%的ListView上使用此代碼,它們確實可以正常工作。 但是,對於一個ListView(它曾經使用過它),它拒絕運行掛起程序。 當我在兩種方法中都添加LineBreaks時。 它到達ListViewColumnSorter.columnClick(listViewKlienci, ref lvwColumnSorterKlienci, sender, e, headerIcons); 然后通過代碼進入varListView.Sort(); 並且它在這里停止..永遠不會到達方法的結尾。 ListView非常簡單,有2列和一些顏色。

private void listViewKlienci_ColumnClick(object sender, ColumnClickEventArgs e) {
        ListViewColumnSorter.columnClick(listViewKlienci, ref lvwColumnSorterKlienci, sender, e, headerIcons);
        ListViewHelper.listViewResize(listViewKlienci);
}

public static void columnClick(ListView varListView, ref ListViewColumnSorter lvwColumnSorter, object sender, ColumnClickEventArgs e, ImageList headerImages) {
        //get list view header
        IntPtr hHeader = SendMessage(varListView.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
        SendMessage(hHeader, HDM_SETIMAGELIST, IntPtr.Zero, headerImages.Handle);
        SortOrder Order = SortOrder.Descending;
        //format icons
        HDITEM hd = new HDITEM {
                                   mask = HDI_IMAGE | HDI_FORMAT
                               };
        for (int i = 0; i < varListView.Columns.Count; i++) {
            //    if (i != e.Column) {
            hd.fmt = HDF_LEFT | HDF_STRING;
            hd.iImage = -1;
            SendMessage(hHeader, HDM_SETITEM, new IntPtr(i), ref hd);
            //    }
        }
        hd.fmt = HDF_LEFT | HDF_STRING | HDF_BITMAP_ON_RIGHT;
        ListViewHelper.enableDoubleBuffer(varListView);
        if (Order != SortOrder.None) {
            hd.fmt |= HDF_IMAGE;
        }
        if (e.Column == lvwColumnSorter.SortColumn) {
            if (lvwColumnSorter.Order == SortOrder.Ascending) {
                hd.iImage = 0;
                lvwColumnSorter.Order = SortOrder.Descending;
            } else {
                hd.iImage = 1;
                lvwColumnSorter.Order = SortOrder.Ascending;
            }
        } else {
            hd.iImage = 1;
            lvwColumnSorter.SortColumn = e.Column;
            lvwColumnSorter.Order = SortOrder.Ascending;
        }
        SendMessage(hHeader, HDM_SETITEM, new IntPtr(e.Column), ref hd);
        varListView.Sort();
    }

並且在Sort()期間執行了很多Compare操作。

    /// <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;
        var listviewX = (ListViewItem) x;
        var listviewY = (ListViewItem) y;
        string s1 = listviewX.SubItems.Count > ColumnToSort ? listviewX.SubItems[ColumnToSort].Text : String.Empty;
        string s2 = listviewY.SubItems.Count > ColumnToSort ? listviewY.SubItems[ColumnToSort].Text : String.Empty;
        int i1;
        int i2;
        DateTime date1;
        DateTime date2;
        decimal d1;
        decimal d2;

        if (int.TryParse(s1, out i1) && int.TryParse(s2, out i2)) {
            compareResult = ObjectCompare.Compare(i1, i2);
        } else if (DateTime.TryParse(s1, out date1) && DateTime.TryParse(s2, out date2)) {
            compareResult = ObjectCompare.Compare(date1, date2);
        } else if (Locale.returnDecimalFromZl(s1, out d1) && Locale.returnDecimalFromZl(s2, out d2)) {
            compareResult = ObjectCompare.Compare(d1, d2);
        } else {
            compareResult = ObjectCompare.Compare(s1, s2);
        }
        // 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;
        }
    }

如果我稍微更改一下代碼並刪除所有if,僅留下一個比較,它會立即返回結果。

        //if (int.TryParse(s1, out i1) && int.TryParse(s2, out i2)) {
        //    compareResult = ObjectCompare.Compare(i1, i2);
        //} else if (DateTime.TryParse(s1, out date1) && DateTime.TryParse(s2, out date2)) {
        //    compareResult = ObjectCompare.Compare(date1, date2);
        //} else if (Locale.returnDecimalFromZl(s1, out d1) && Locale.returnDecimalFromZl(s2, out d2)) {
        //    compareResult = ObjectCompare.Compare(d1, d2);
        //} else {
            compareResult = ObjectCompare.Compare(s1, s2);
       // }

看來這就是原因。。。但是它在Visual Studio之外運行良好,只是在Visual Studio中,這會導致速度減慢。

我進一步開始添加更多的compareResults,只有最后一個導致速度下降:

 public static bool returnDecimalFromZl(string dataToCheck, out decimal value) {
        if (dataToCheck.Trim() != "") { // && dataToCheck.Contains(" zł")) {
            try {
                value = Decimal.Parse(dataToCheck.Trim(), NumberStyles.Number | NumberStyles.AllowCurrencySymbol);
                return true;
            } catch {
                value = 0m;
                return false;
            }
        }
        value = 0m;
        return false;
    }

如果我將其更改為:

    public static bool returnDecimalFromCurrency(string dataToCheck, out decimal value) {
        if ((dataToCheck.Trim() != "")  && (dataToCheck.Contains(" zł"))) {
            try {
                value = Decimal.Parse(dataToCheck.Trim(), NumberStyles.Number | NumberStyles.AllowCurrencySymbol);
                return true;
            } catch {
                value = 0m;
                return false;
            }
        }
        value = 0m;
        return false;
    }

它立即開始工作..方法上更多的是&& (dataToCheck.Contains(" zł")) 奇怪的東西!

EDIT1:有趣的事情是我讓它運行5-10分鍾后,它已成功從Sort中返回...

編輯2。 使用第一欄進行排序。 第二列包含人員姓名(1200〜名)

編輯3。 在Visual Studio外部進行排序可以很好地工作(我進入了項目中的BIN目錄並執行了我的應用程序-在1秒內進行排序)。 因此,似乎只有Visual Studio受到影響。 我什至將舊的硬盤放入裝有不同(相同版本)Visual Studio的計算機中,但問題仍然存在。

編輯4。 如果我使用諸如RedGate ANTS探查器之類的PROFILER從Visual Studio問題中啟動時不顯示問題,並且ListView Sorting非常快... $#^ $ * $#%

您發現了為什么在.NET 2.0版中添加了TryParse()方法。 切換到“輸出”窗口,以觀察成千上萬的“首次機會”異常通知消息。 附加調試器后,異常處理的開銷變得非常大

發現我改變方法后

 public static bool returnDecimalFromZl(string dataToCheck, out decimal value) {
        if (dataToCheck.Trim() != "") { 
            try {
                value = Decimal.Parse(dataToCheck.Trim(), NumberStyles.Number | NumberStyles.AllowCurrencySymbol);
                return true;
            } catch {
                value = 0m;
                return false;
            }
        }
        value = 0m;
        return false;
    }

如果我將其更改為:

    public static bool returnDecimalFromZl(string dataToCheck, out decimal value) {
        if ((dataToCheck.Trim() != "")  && (dataToCheck.Contains(" zł"))) {
            try {
                value = Decimal.Parse(dataToCheck.Trim(), NumberStyles.Number | NumberStyles.AllowCurrencySymbol);
                return true;
            } catch {
                value = 0m;
                return false;
            }
        }
        value = 0m;
        return false;
    }

程序也開始在Visual Studio中正常工作。 在Visual Studio外部和內部使用時,為什么我的行為不正常? 1200個物體的速度差為5-10分鍾:/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM