使用托管 API 关闭 WiFi 连接
我正在使用 托管 WiFi API 编写程序。以下是我如何获取范围内的所有网络:
void UpdateNetworks()
{
networks = new List<Wlan.WlanAvailableNetwork>();
WlanClient client = new WlanClient();
foreach(WlanClient.WlanInterface iface in client.Interfaces)
{
Wlan.WlanAvailableNetwork[] nets = iface.GetAvailableNetworkList(0);
foreach(Wlan.WlanAvailableNetwork net in nets)
networks.Add(net);
}
}
问题是,在调用此方法 18 次后,我无法再连接:
(0x80004005):已尝试 建立与网络的会话 服务器,但已经太多了 与该服务器建立的会话。
这是抛出异常的构造函数:
public WlanClient()
{
Wlan.ThrowIfError(
Wlan.WlanOpenHandle(Wlan.WLAN_CLIENT_VERSION_XP_SP2, IntPtr.Zero, out negotiatedVersion, out clientHandle));
try
{
Wlan.WlanNotificationSource prevSrc;
wlanNotificationCallback = new Wlan.WlanNotificationCallbackDelegate(OnWlanNotification);
Wlan.ThrowIfError(
Wlan.WlanRegisterNotification(clientHandle, Wlan.WlanNotificationSource.All, false, wlanNotificationCallback, IntPtr.Zero, IntPtr.Zero, out prevSrc));
}
catch
{
Wlan.WlanCloseHandle(clientHandle, IntPtr.Zero);
throw;
}
}
我相信这是因为客户端永远不会关闭它打开的连接。我如何显式关闭它们? catch 块中有句柄关闭,但它需要访问客户端的私有部分。
I'm writing a program using the Managed WiFi API. Here's how I get all the networks in range:
void UpdateNetworks()
{
networks = new List<Wlan.WlanAvailableNetwork>();
WlanClient client = new WlanClient();
foreach(WlanClient.WlanInterface iface in client.Interfaces)
{
Wlan.WlanAvailableNetwork[] nets = iface.GetAvailableNetworkList(0);
foreach(Wlan.WlanAvailableNetwork net in nets)
networks.Add(net);
}
}
The problem is that after 18 calls to this method I can no longer connect:
(0x80004005): An attempt was made to
establish a session to a network
server, but there are already too many
sessions established to that server.
Here's the constructor that's throwing the exception:
public WlanClient()
{
Wlan.ThrowIfError(
Wlan.WlanOpenHandle(Wlan.WLAN_CLIENT_VERSION_XP_SP2, IntPtr.Zero, out negotiatedVersion, out clientHandle));
try
{
Wlan.WlanNotificationSource prevSrc;
wlanNotificationCallback = new Wlan.WlanNotificationCallbackDelegate(OnWlanNotification);
Wlan.ThrowIfError(
Wlan.WlanRegisterNotification(clientHandle, Wlan.WlanNotificationSource.All, false, wlanNotificationCallback, IntPtr.Zero, IntPtr.Zero, out prevSrc));
}
catch
{
Wlan.WlanCloseHandle(clientHandle, IntPtr.Zero);
throw;
}
}
I believe this is because the client never closes the connections it opens. How do I close them explicitly? There's handle closing in the catch
block, but it requires access to the client's private parts.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我有同样的问题。
我尝试了 Joe White 先生的解决方案,但收到一个错误,即 wlanClient 无法转换为 System.IDisposable。
由于这个问题与 WlanClient 实例的处理有关,因此我只定义了 1 个实例作为类成员,并在方法 [void UpdateNetworks()] 中多次使用它。我没有收到任何错误。
删除行
从方法中 并在类中定义它。如下所示:
参考:托管 WiFi 错误
I have the same problem.
I tried Mr Joe White solution but I received an error that wlanClient cannot be converted to System.IDisposable.
Since this problem is related to disposal of WlanClient instances, I only defined 1 instance as class member and used it so many times in method [void UpdateNetworks()]. I did not receive any error.
Remove line
from your method and define it in your class. like the following:
Reference: Managed WiFi error
由于您仅在一定次数的迭代后才会看到问题,因此问题可能是某种资源耗尽,这听起来像是资源没有及时清理。
从上面的评论来看,听起来您没有处理您的
WlanClient
实例,这可能是问题的一部分(或全部)。不过,我可以理解为什么你不处理它们,因为它们没有给你任何明显的方法来处理它们。对他们来说,这似乎是一个真正有问题的设计。有各种各样的设计指南说像这样的类应该为您提供公共Dispose
方法或公共Close
方法,但即使它们都具有 这些方法,他们故意将它们设为私有。但该类确实实现了 IDisposable,因此您仍然可以通过添加 using 块来清理它:
这将确保当前流中的所有对象资源都得到清理离开
using
块(即使流程因为出现异常而离开)。您的连接将被关闭,您的非托管内存将被释放,以及其他任何需要发生的事情。Since you're seeing problems only after a certain number of iterations, the problem is likely resource exhaustion of some sort, which sounds like resources aren't getting cleaned up in a timely manner.
From the comments above, it sounds like you're not disposing your
WlanClient
instances, which may be part (or all) of the problem. I can understand why you're not disposing them, though, because they don't give you any obvious way to do so. This seems like a really problematic design on their part. There are all kinds of design guidelines that say a class like this should give you either a publicDispose
method or a publicClose
method, but even though they have both those methods, they deliberately made them both private.But the class does implement
IDisposable
, so you can still clean it up by adding ausing
block:This will make sure all of the object's resources get cleaned up at the moment flow leaves the
using
block (even if flow is leaving because there was an exception). Your connections will be closed, your unmanaged memory released, and whatever else needs to happen.