代码函数
+ -

Windows 发送UVC XU Set命令卡死的一种处理办法

2021-09-28 30 1

Windows系统应用层可以通过获取UVC设备的IKsControl对象,然后调用KsProperty来GET/SET XU命令。经过测试发现,如果调用SET命令的时候设备拔出了,有一定的概率会出现卡死现象,KsProperty这个方法卡住了。复现方法很简单,获取IKsControl对象,然后Sleep 5秒钟,调用Sleep之后立即手动拔出设备,然后再调用KsProperty去Set命令,100%会卡死。

如果是在UI线程调用Set命令导致卡死就惨了,整个UI都会卡住,UI程序就挂了,没得恢复。由于KsProperty参数很简单,没有哪个参数设置可以避开卡死问题,因此需要调用者去处理规避。

 STDMETHOD(KsProperty)(
        THIS_
        IN PKSPROPERTY Property,
        IN ULONG PropertyLength,
        IN OUT LPVOID PropertyData,
        IN ULONG DataLength,
        OUT ULONG* BytesReturned
    ) PURE;

经过思考,我设计了一种普遍性的方法可以规避这种调用有可能卡死的问题。 代码如下:

#include "stdafx.h"
#include <stdio.h>
#include <windows.h>

BOOL 
CallTimeoutFunction(
     LPTHREAD_START_ROUTINE lpStartAddress, 
     LPVOID lpParameter,
     DWORD timeoutSec)
{
    if (NULL == lpStartAddress)
    {
        return FALSE;
    }

    BOOL retVal = FALSE;
    HANDLE hThread = CreateThread(NULL, 0, lpStartAddress, lpParameter, 0, NULL);
    if (WAIT_OBJECT_0 == WaitForSingleObject(hThread, timeoutSec))
    {
        retVal = TRUE;
        printf("finish!\n");
    }
    else
    {
        TerminateThread(hThread, -1);        
        printf("timeout!\n");
    }
    CloseHandle(hThread);
    return retVal;
}


DWORD WINAPI TimeoutFunc(LPVOID lpParameter)
{
    printf("call func\n");
    Sleep(50*1000);
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    CallTimeoutFunction(TimeoutFunc, NULL, 100);
    printf("main over\n");
}

在main中调用了一个Sleep 50s的函数,如果没有处理,程序必定会卡住50s, 处理之后,立马就调用完毕了,输出结果:

call func
timeout!
main over

CallTimeoutFunction是一个超时调用函数,可以设置调用某个函数的等待超时时间,超过了就返回。CallTimeoutFunction内部实现也比较简单,开启一个线程,然后调用WaitForSingleObject设置好超时时间,等待线程结束,如果超时就返回FALSE,否则返回TRUE.

这样就把一个卡死的调用变成超时等待调用,传递合适的参数,再怎么调用都不会卡死了。

当然可以再深度封装一下,在线程里while(1)等待调用事件,只有第一次或者卡死之后调用再创建线程,这样就大大减小了线程的创建次数,提高了效率。

在我的XU调试工具就加了这样的处理,打开设备之后,拔出设备,再去点击SET按钮,UI程序并不会卡死,会提示超时了,用起来体验也好一些。

0 篇笔记 写笔记

Windows 发送UVC XU Set命令卡死的一种处理办法
Windows系统应用层可以通过获取UVC设备的IKsControl对象,然后调用KsProperty来GET/SET XU命令。经过测试发现,如果调用SET命令的时候设备拔出了,有一定的概率会出现卡死现象,KsProperty这个方法卡住了。复现方法很简单,获取IKsControl对象,然后Sle......
作者信息
HelloWorld
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!