Закрытие WiFi-подключений с помощью управляемого API
Я пишу программу с использованием API Managed WiFi. Вот как я получаю все сети в диапазоне:
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
блок, но он требует доступа к частным частям клиента.
2 ответа
Поскольку вы видите проблемы только после определенного количества итераций, проблема, скорее всего, заключается в исчерпании ресурсов какого-либо рода, что звучит так, как будто ресурсы не очищаются своевременно.
Судя по комментариям выше, кажется, что вы не избавляетесь от WlanClient
случаи, которые могут быть частью (или все) проблемы. Я могу понять, почему вы не избавляетесь от них, потому что они не дают вам очевидного способа сделать это. Это кажется действительно проблематичным дизайном с их стороны. Существуют всевозможные рекомендации по дизайну, в которых говорится, что подобный класс должен Dispose
метод или общественность Close
метод, но хотя у них есть оба этих метода, они сознательно сделали их обоих частными.
Но класс действительно реализует IDisposable
, так что вы все еще можете очистить его, добавив using
блок:
using (var wlanClient = new WlanClient()) {
....
} // wlanClient will be disposed when flow leaves the block
Это обеспечит очистку всех ресурсов объекта в тот момент, когда поток покидает using
блок (даже если поток уходит из-за исключения). Ваши соединения будут закрыты, ваша неуправляемая память будет освобождена, и все остальное должно произойти.
У меня та же проблема. Я попробовал решение г-на Джо Уайта, но получил ошибку, что wlanClient не может быть преобразован в System.IDisposable.
Поскольку эта проблема связана с удалением экземпляров WlanClient, я определил только 1 экземпляр как член класса и использовал его много раз в методе [void UpdateNetworks()]. Я не получил ни одной ошибки.
Удалить строку
WlanClient client = new WlanClient();
от вашего метода и определить его в вашем классе. как следующее:
public partial class frm_main : Form
{
private WlanClient client = new WlanClient();
private void UpdateNetworks()
{
var networks = new List<Wlan.WlanAvailableNetwork>();
foreach (WlanClient.WlanInterface iface in client.Interfaces)
{
Wlan.WlanAvailableNetwork[] nets = iface.GetAvailableNetworkList(0);
foreach (Wlan.WlanAvailableNetwork net in nets)
networks.Add(net);
}
MessageBox.Show(networks.Count.ToString());
}
}
Справка: ошибка управляемого WiFi