确定应用程序是否被阻塞/忙碌?

8
我正在尝试使用C#/.NET 4.0自动化外部应用程序的GUI。被自动化的应用程序(AUT)是一个VB6应用程序。
在执行操作或单击按钮时,AUT有时需要等待DB响应很长时间。当应用程序等待DB结果时,应用程序本身是空闲的(不会注册太多的CPU使用率),但是被阻塞了(无法单击或与之交互)。
-到目前为止,我已经尝试将鼠标指针(沙漏)作为指示器,但有时应用程序被阻塞但光标是正常的。因此这是不可靠的。
-我尝试查看AUT的主进程中的TotalProcessorTime (这测量应用程序是空闲还是繁忙),但像我所说,有时应用程序是空闲的,但仍然被阻塞。
因此,我想利用StackOverflow上的经验,看看是否有人已经知道如何处理这个问题,并且/或者您是否有任何想法可以实现这一点。
谢谢
编辑:
我一直在摸索,刚刚发现了一些东西。
虽然AUT被阻塞,但它没有响应键盘或鼠标输入。但是,如果我向窗口发送WM_LBUTTONCLICK消息,我可以确认消息正在处理(并且UI会发生变化)。
因此,我猜他们在进行DB调用时特意阻塞了应用程序。

UI已禁用吗?主要的UI线程是否在工作线程上阻塞?如果您尝试与应用程序交互,是否会看到窗口幽灵化现象? - David Heffernan
你无法与主UI交互,但我认为主UI线程没有阻塞,因为当您尝试与其交互时,您不会看到任何“幽灵”现象。它只是什么也不做。所有控件/UI仍然“启用”。 - DanyO
使用Spy++检查主窗口是否被禁用。如果消息队列正在被泵送,并且您无法调用UI操作,则我猜测AUT中的某些内容必须被禁用了。 - David Heffernan
我刚用Spy++验证了一下,每当应用程序被阻塞时,在Spy++中,“Window Prod”会标记为“不可用”。(而当它没有被阻塞时,它会显示进程的地址) - DanyO
1个回答

3

您可以检查该应用程序的用户界面是否响应:

获取该应用程序的进程实例并检查其Responding属性,例如:

//To get the process instance
Process  application = null;
foreach (var process in Process.GetProcesses())
{
    if (process.ProcessName == "The Process Name")
    {
        application = process;
        break;
    }
}

//to check if the process UI is not responding
if (application.Responding)
{ 
    //
}

编辑:您可以修改application.Responding检查使用的超时时间,详情请参见此处


我刚刚验证了一下,在应用程序似乎被阻塞的时候,application.Responding返回TRUE,因此我们无法使用它... - DanyO
@DanyO:也许你的进程没有 MainWindowHandlemsdn 如果进程没有 MainWindowHandle,则此属性返回 true。,否则这个属性应该是可以工作的,“AFAIK”,例如:检查 this - Jalal Said
我刚刚验证了一下,该进程确实具有有效的MainWindowHandle。根据文档,“Process.Responding”是否仅适用于被认为已挂起的应用程序?我正在测试的应用程序实际上并没有挂起,它只是在等待从数据库接收响应时被阻塞。 - DanyO
@DanyO:请查看这个链接 - Jalal Said
刚刚尝试了你建议的链接,但当应用程序被阻止时,它仍然返回"TRUE"。我甚至尝试将超时时间降低到1,但仍然返回TRUE。 - DanyO
@DanyO:我不知道当应用程序阻塞时你是如何测试的,但这里有一个例子: `ThreadPool.QueueUserWorkItem(new WaitCallback((_) => { while (true) { if (!application.Responding) { Console.WriteLine("Not responding at {0}", DateTime.Now); } Thread.Sleep(100); }}));` - Jalal Said

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接