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

WPF调用NetworkAdapter.GetConnectedProfileAsync遇线程错误求助

WPF中使用WinRT WiFi API触发跨线程错误的解决方法

问题描述

开发WPF应用时,借助WinRT库实现WiFi管理功能,需要获取当前连接网络的配置文件。代码逻辑无明显问题,但触发了线程错误。已确认代码运行在线程1,且是应用中唯一调用该类API的代码,不清楚该API的线程要求。

错误信息

The application called an interface that was marshalled for a different thread. (0x8001010E (RPC_E_WRONG_THREAD))

相关代码

var access = await WiFiAdapter.RequestAccessAsync();
if (access != WiFiAccessStatus.Allowed) { Networks = new List<WiFiAvailableNetwork>(); return; }

var adapters = await WiFiAdapter.FindAllAdaptersAsync();
if (!adapters.Any()) return;

Adapter = adapters.First();
await Adapter.ScanAsync();
Networks = Adapter.NetworkReport.AvailableNetworks;

IReadOnlyList<ConnectionProfile> profiles = Array.Empty<ConnectionProfile>();
Application.Current.Dispatcher.Invoke(() => profiles = NetworkInformation.GetConnectionProfiles());
ConnectionProfiles = profiles;

ConnectionProfile profile = default;
try { profile = await Adapter.NetworkAdapter.GetConnectedProfileAsync(); } // <= 此处报错
catch (Exception ex) { Log.Exception(ex); }

已尝试的无效写法

await Application.Current.Dispatcher.Invoke(async () => profile = await Adapter.NetworkAdapter.GetConnectedProfileAsync());
await Application.Current.Dispatcher.InvokeAsync(async () => profile = await Adapter.NetworkAdapter.GetConnectedProfileAsync());

解决思路与代码修正

WinRT API具备线程亲和性,即创建WinRT对象的线程必须与访问该对象的线程保持一致。你之前的代码中,Adapter对象是在await后的后台线程上下文获取的,后续在UI线程访问它的NetworkAdapter属性时,就会触发跨线程调用错误。

正确的做法是将所有WinRT相关的API调用逻辑封装到同一个线程上下文中,避免跨线程访问WinRT对象:

修正后的代码

// 将整个WinRT操作逻辑放到UI线程调度中执行
await Application.Current.Dispatcher.InvokeAsync(async () =>
{
    var access = await WiFiAdapter.RequestAccessAsync();
    if (access != WiFiAccessStatus.Allowed) 
    { 
        Networks = new List<WiFiAvailableNetwork>(); 
        return; 
    }

    var adapters = await WiFiAdapter.FindAllAdaptersAsync();
    if (!adapters.Any()) return;

    Adapter = adapters.First();
    await Adapter.ScanAsync();
    Networks = Adapter.NetworkReport.AvailableNetworks;

    // 无需额外调度,直接在当前上下文调用NetworkInformation API
    ConnectionProfiles = NetworkInformation.GetConnectionProfiles();

    try 
    { 
        var profile = await Adapter.NetworkAdapter.GetConnectedProfileAsync();
        // 在这里处理获取到的连接配置文件
    } 
    catch (Exception ex) { Log.Exception(ex); }
});

替代方案(.NET 6+ 推荐)

如果你的应用基于.NET 6及以上版本,可使用WinRT原生的DispatcherQueue进行线程调度,适配性更好:

var dispatcherQueue = DispatcherQueue.GetForCurrentThread();
await dispatcherQueue.TryEnqueue(async () =>
{
    // 所有WinRT API调用逻辑都放在这里
    var access = await WiFiAdapter.RequestAccessAsync();
    // ... 后续逻辑同上
});

核心原因总结

WinRT对象绑定到创建它的线程上下文,无法跨线程直接访问。你之前的错误在于拆分了WinRT对象的创建与属性访问操作到不同线程,将整个流程统一到同一个调度上下文即可解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 13:47:35