Отличная библиотека Майк, большое спасибо за эту огромную работу.
Проблема в том, что я хочу заполнить InputReport данными:
InputReport = device.ReadReport ();
где InputReport:
HidLibrary.HidReport InputReport = новый HidLibrary.HidReport (device.Capabilities.InputReportByteLength);
Это очень большая утечка памяти, особенно когда я читаю отчеты в асинхронном режиме с устройства (например, 100 раз в секунду). За несколько минут это может занять сотни мегабайт.
Я новичок в программировании на C # и не нашел решения проблемы, описанной выше; (
Приветствую!
Качарт,
К сожалению, этот код довольно старый, и у меня не было времени дать его
любой ТСХ. На данный момент у меня есть это только для справки. Ты лучший
ставка на форк / улучшение.
м
В вс, 14 августа 2011 г., 10:37, kaczart <
[email protected]> написал:
Отличная библиотека Майк, большое спасибо за эту огромную работу.
Проблема в том, что я хочу заполнить InputReport данными:
InputReport = device.ReadReport ();
где InputReport:
HidLibrary.HidReport InputReport = новый
HidLibrary.HidReport (ukp.Capabilities.InputReportByteLength);Это очень большая утечка памяти, особенно когда я читаю отчеты в асинхронном режиме.
режим с устройства (например, 100 раз в секунду). Через несколько минут это может
занимает сотни мегабайт.Я новичок в программировании на C # и не нашел решения проблемы
описанный выше; (Приветствую!
Ответьте на это письмо напрямую или просмотрите его на GitHub:
https://github.com/mikeobrien/HidLibrary/issues/11
Качарт,
Вы нашли решение? Я просто заметил то же самое.
Отличная библиотека Майк, большое спасибо! Я работаю с USB-шкалой Endicia, и это довольно весело.
jrockfl,
к сожалению, у меня не было времени и навыков, чтобы исправить эту проблему :(
Приветствую
Проблема в том, что HidReport и Devicedata не освобождены, поэтому они ждут сборки мусора.
Это простое решение - выпустить его после того, как он будет обработан ...
Наконец мне пришлось исправить эту проблему, и я делюсь тем, что нашел.
1) Прежде всего, каждый метод чтения / записи в библиотеке проверяет, подключено ли устройство, что требует больших затрат производительности, потому что метод IsConnected вызывает каждый раз EnumerateHidDevices (). На практике, когда я отправляю большой пакет данных с устройства, хост ПК работает медленнее, чем устройство HID, и некоторые пакеты теряются из-за ограниченного кольцевого буфера (32 отчета по умолчанию, может быть увеличено до 512, но это не окончательное решение).
пс. Вы можете расширить свой кольцевой буфер с 32 до 512 отчетов, позвонив:
NativeMethods .HidD_SetNumInputBuffers ((int) device.ReadHandle, 512); // Это будет работать для XP и более поздних версий.
2) Во-вторых, в EnumerateHidDevices () есть ОГРОМНАЯ утечка памяти из-за "yield return devicePath;" в строке 69 и NativeMethods.SetupDiDestroyDeviceInfoList (deviceInfoSet); никогда не назовут.
Мое решение:
1) Не вызывайте IsConnected при каждом чтении / записи. Сделайте дополнительную переменную isConnected в HidDevice:
public bool isConnected;
Установите для переменной значение true после успешного подключения (например, в вашей функции Connect ()):
device.isConnected = true;
Обновляйте его во всех событиях DeviceEventMonitorInserted () и DeviceEventMonitorRemoved (), например:
if (Inserted! = null) Inserted ();
заменить:
если (вставлено! = ноль)
{
isConnected = true;
Вставлено ();
}
а также:
если (Удалено! = null) Удалено ();
заменить:
if (Удалено! = null)
{
isConnected = false;
Удаленный();
}
Затем проверяйте эту переменную при каждой функции вызова чтения / записи:
if (isConnected) вместо if (IsConnected)
Каждый раз, когда вам нужно проверить, подключено ли устройство, проверяйте состояние публичной переменной isConnected. У меня работает - загрузка процессора 0-1% вместо 10-20% для потока чтения.
2) в HidDevice.cs строку # 69 удалите:
// yield return devicePath;
Это позволит NativeMethods .SetupDiDestroyDeviceInfoList (deviceInfoSet); называться должным образом.
Затем после NativeMethods .SetupDiDestroyDeviceInfoList (deviceInfoSet) добавьте:
foreach (строка devicePath в устройствах)
yield return devicePath;
Это исправит ОГРОМНУЮ утечку памяти (в моем случае около 256 МБ на каждый 1 МБ полученных данных)
Надеюсь, это хепс.
круто, спасибо за подсказки, kaczart !!!
Вот мой предлагаемый способ решения проблемы с производительностью, которую заметил Качарт (и я):
https://github.com/macaba/HidLibrary/commit/8f1864e1351ccca4772d5bbc18a0f94d7ba07fe7
Использование происходит по следующим направлениям:
device.ConnectionCheckOverride = device.IsConnected;
methodRequiringFasterUSBReadWrite();
device.ConnectionCheckOverride = false;
Это сократило время выполнения моего тестового примера для массовой передачи данных по USB с 159 до 47 секунд.
Мне не нравилось решение kaczart просто потому, что свойство IsConnected используется в HidDeviceEventMonitor, поэтому необходимо сохранить исходную функциональность перечисления подключенных в данный момент USB-устройств. Проще говоря; Я не думаю, что события Inserted и Removed когда-либо будут вызываться в коде kaczart (после беглого просмотра).
Проверка подключения устройства при каждом чтении и записи является основным узким местом производительности в высокочастотных приложениях. В моем конкретном случае было в 30 раз быстрее предположить, что устройство подключено, а не перепроверять подключение устройства; круговые поездки упали с 70 мс до 2 мс.
Поэтому я просто написал пару методов расширения для обработки моего собственного ввода-вывода для быстрого использования пула:
[DllImport("hid.dll", SetLastError = true)]
static internal extern bool HidD_SetOutputReport(IntPtr hidDeviceObject, byte[] lpReportBuffer, int reportBufferLength);
[DllImport("kernel32.dll", SetLastError = true)]
static internal extern bool ReadFile(IntPtr hFile, [Out] byte[] lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
public static bool FastWrite(this HidLibrary.HidDevice device, byte[] outputBuffer)
{
try
{
if (NativeMethods.HidD_SetOutputReport(device.Handle, outputBuffer, outputBuffer.Length))
return true;
else
return false;
}
catch
{
return false;
}
}
public static ReadStatus FastRead(this HidLibrary.HidDevice device, byte[] inputBuffer)
{
try
{
uint bytesRead;
if (NativeMethods.ReadFile(device.Handle, inputBuffer, (uint)inputBuffer.Length, out bytesRead, IntPtr.Zero))
{
return ReadStatus.Success;
}
else
{
return ReadStatus.NoDataRead;
}
}
catch (Exception)
{
return ReadStatus.ReadError;
}
}
Самый полезный комментарий
Вот мой предлагаемый способ решения проблемы с производительностью, которую заметил Качарт (и я):
https://github.com/macaba/HidLibrary/commit/8f1864e1351ccca4772d5bbc18a0f94d7ba07fe7
Использование происходит по следующим направлениям:
Это сократило время выполнения моего тестового примера для массовой передачи данных по USB с 159 до 47 секунд.
Мне не нравилось решение kaczart просто потому, что свойство IsConnected используется в HidDeviceEventMonitor, поэтому необходимо сохранить исходную функциональность перечисления подключенных в данный момент USB-устройств. Проще говоря; Я не думаю, что события Inserted и Removed когда-либо будут вызываться в коде kaczart (после беглого просмотра).