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

C# WinForm中WebSocket OnMessage监听内向ListView添加项异常

问题根因

抛出System.InvalidOperationException、ListView不更新是典型的跨线程访问UI控件违规:

  • WebSocket的OnMessage回调运行在独立的后台工作线程,而非UI主线程
  • WinForm的所有UI控件都有线程亲和性,只能在创建控件的UI主线程上执行修改操作,后台线程直接操作控件就会触发该异常,和控制台能正常输出数据不冲突——控制台输出没有线程限制。
修复代码

通过控件自带的线程封送方法,把ListView更新逻辑投递到UI主线程执行即可,修改后的回调代码:

private void Ws_OnMessage(object sender, MessageEventArgs e)
{
    dynamic data = JsonConvert.DeserializeObject<dynamic>(e.Data);
    double price = data["data"][0]["p"];
    string stock = data["data"][0]["s"];
    Console.WriteLine($"{stock} {price}");

    // 跨线程判断
    if (portfolioList.InvokeRequired)
    {
        // 异步封送到UI线程执行更新,不阻塞WebSocket消息接收
        portfolioList.BeginInvoke((Action)(() =>
        {
            var item = new ListViewItem(new[] { stock, price.ToString() });
            portfolioList.Items.Add(item);
        }));
        return;
    }

    // 处于UI线程时直接更新
    var uiItem = new ListViewItem(new[] { stock, price.ToString() });
    portfolioList.Items.Add(uiItem);
}
注意点
  • 不要在OnMessage回调里直接写UI更新逻辑,所有涉及界面控件修改的代码都要做跨线程检查
  • 优先用BeginInvoke做异步封送,避免阻塞WebSocket的消息接收线程导致消息堆积;如果需要同步拿到UI更新结果再做后续处理,再使用Invoke
  • 如果项目是WPF框架,替换成Dispatcher.BeginInvoke做线程封送即可,核心逻辑一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:27:21