You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ListView中线程安全调用FindItemWithText的最优实现方案求教

针对你用FindItemWithText实现跨线程搜索ListView的场景,我整理几个更优的实现思路,帮你简化代码同时提升性能:

首先先补全你给出的初步实现代码(方便对照参考):

string SearchLocal(string findstr) 
{ 
    string item = findstr; 
    if (lvContactsLocal.InvokeRequired) 
    { 
        lvContactsLocal.Invoke((MethodInvoker)delegate () 
        { 
            var foundItem = lvContactsLocal.FindItemWithText(findstr, true, 0);
            if (foundItem != null)
            {
                item = foundItem.Text;
                // 可能包含选中、滚动到项等UI操作
            }
        });
    }
    else
    {
        var foundItem = lvContactsLocal.FindItemWithText(findstr, true, 0);
        if (foundItem != null)
        {
            item = foundItem.Text;
        }
    }
    return item;
}

优化思路1:封装通用线程安全扩展方法

把跨线程调用的逻辑封装成扩展方法,避免重复编写Invoke判断代码,后续其他ListView也能直接复用:

public static class ListViewExtensions
{
    // 线程安全的FindItemWithText封装
    public static ListViewItem SafeFindItemWithText(this ListView listView, string text, bool includeSubItemsInSearch, int startIndex)
    {
        if (listView.InvokeRequired)
        {
            // 用Func委托传递参数并返回结果,替代MethodInvoker
            return (ListViewItem)listView.Invoke(
                new Func<string, bool, int, ListViewItem>(SafeFindItemWithText), 
                text, includeSubItemsInSearch, startIndex);
        }
        return listView.FindItemWithText(text, includeSubItemsInSearch, startIndex);
    }
}

之后你的搜索方法可以简化成:

string SearchLocal(string findstr) 
{ 
    var foundItem = lvContactsLocal.SafeFindItemWithText(findstr, true, 0);
    return foundItem?.Text ?? findstr;
}

优化思路2:异步搜索避免阻塞UI

如果你的ListView数据量较大,直接在UI线程调用FindItemWithText可能会导致界面卡顿。可以把搜索逻辑放到后台线程,仅在需要更新UI时回到主线程:

async Task<string> SearchLocalAsync(string findstr)
{
    // 先把ListView的项数据复制到后台可访问的集合(避免跨线程直接操作控件)
    List<ListViewItem> itemsCopy = null;
    await lvContactsLocal.InvokeAsync(() => 
    {
        itemsCopy = lvContactsLocal.Items.Cast<ListViewItem>().ToList();
    });

    // 在后台线程执行搜索逻辑(可自定义匹配规则)
    var foundItem = await Task.Run(() => 
    {
        return itemsCopy.FirstOrDefault(item => 
            item.Text.Contains(findstr) || 
            item.SubItems.Cast<ListViewItem.ListViewSubItem>().Any(sub => sub.Text.Contains(findstr)));
    });

    // 回到UI线程执行选中、滚动等操作
    if (foundItem != null)
    {
        await lvContactsLocal.InvokeAsync(() => 
        {
            lvContactsLocal.SelectedItems.Clear();
            foundItem.Selected = true;
            lvContactsLocal.EnsureVisible(foundItem.Index);
        });
        return foundItem.Text;
    }
    return findstr;
}

优化思路3:提前缓存搜索数据(适合高频搜索场景)

如果需要频繁执行搜索操作,可以提前把ListView的文本数据缓存到线程安全的集合中,避免每次搜索都从控件读取数据:

// 定义缓存集合,存储所有项的文本(包含子项)
private List<string> _searchCache;

// 初始化缓存(比如在ListView加载完成后调用)
private void InitializeSearchCache()
{
    _searchCache = lvContactsLocal.Items.Cast<ListViewItem>()
        .Select(item => $"{item.Text}|{string.Join("|", item.SubItems.Cast<ListViewItem.ListViewSubItem>().Select(sub => sub.Text))}")
        .ToList();
}

// 搜索方法
string SearchLocal(string findstr)
{
    var matchedText = _searchCache.FirstOrDefault(text => text.Contains(findstr));
    if (matchedText != null)
    {
        // 找到匹配内容后,回到UI线程定位到对应项
        lvContactsLocal.Invoke(() => 
        {
            var foundItem = lvContactsLocal.FindItemWithText(matchedText.Split('|')[0], true, 0);
            if (foundItem != null)
            {
                foundItem.Selected = true;
                lvContactsLocal.EnsureVisible(foundItem.Index);
            }
        });
        return matchedText.Split('|')[0];
    }
    return findstr;
}

注意:当ListView的项发生添加、删除、修改时,需要同步更新_searchCache,保证缓存数据与控件一致。

内容的提问来源于stack exchange,提问作者user9616781

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:35:05