首页 > 其他分享 >为方法增加一个超时等待

为方法增加一个超时等待

时间:2022-08-20 17:22:56浏览次数:100  
标签:string int 等待 timeout hWnd 超时 方法 public

为方法增加一个超时等待

FindWindow 查找窗口直接执行可能窗口还没有准备好,返回结果必然是0。通常使用 Thread.Sleep 进行阻塞等待,是一种有效的手段。因计算机CPU运算效率差异,不能保证及时准确的得到想要的结果。所以有必要使用一个保证效率的基础上并可控的方式,下面是我的处理方式,代码使用 C# 编写,其他语言照葫芦画瓢。

TimeoutMonitor.cs

/// <summary>
/// 超时监视器
/// </summary>
public class TimeoutMonitor
{
    readonly int _tickCount;

    /// <summary>
    /// 创建一个超时监视器
    /// </summary>
    /// <param name="timeout">超时时间(毫秒)</param>
    public TimeoutMonitor(int timeout)
    {
        _tickCount = Environment.TickCount;
        Timeout = timeout;
    }

    /// <summary>
    /// 超时时间(毫秒)
    /// </summary>
    public int Timeout { get; }

    /// <summary>
    /// 完成的
    /// </summary>
    public bool IsCompleted => Environment.TickCount - _tickCount > Timeout;

    /// <summary>
    /// 调用超时,如果超时将抛出 TimeoutException 错误
    /// </summary>
    /// <param name="error">错误描述</param>
    public void ThrowIfTimeout(string error) => ThrowIfTimeout(error, 0);

    /// <summary>
    /// 调用超时,如果超时将抛出 TimeoutException 错误
    /// </summary>
    /// <param name="error">错误描述</param>
    /// <param name="sleepTimeout">阻塞间隔(毫秒)</param>
    public void ThrowIfTimeout(string error, int sleepTimeout)
    {
        if (IsCompleted) throw new TimeoutException(error);
        if (sleepTimeout > 0) Thread.Sleep(sleepTimeout);
    }

    /// <summary>
    /// 根据条件调用超时,如果超时将抛出 TimeoutException 错误
    /// </summary>
    /// <param name="func">返回 true 时立即跳出后续</param>
    /// <param name="timeout">超时时间(毫秒)</param>
    /// <param name="error">错误描述</param>
    public static void ThrowIfTimeout(Func<bool> func, int timeout, string error)
    {
        var tickCount = Environment.TickCount;
        while (Environment.TickCount - tickCount < timeout) if (func()) return;
        throw new TimeoutException(error);
    }

    /// <summary>
    /// 等待超时退出
    /// </summary>
    /// <param name="func">返回 true 时立即跳出后续</param>
    /// <param name="timeout">超时时间(毫秒)</param>
    /// <returns>返回 true 未超时,反之 false 超时</returns>
    public static bool WaitTimeout(Func<bool> func, int timeout)
    {
        var tickCount = Environment.TickCount;
        while (Environment.TickCount - tickCount < timeout) if (func()) return true;
        return false;
    }
}

例子

可适用大多数非阻塞的方法:等待文件完全写入、等待窗口关闭……

FindWindowTimeout

在指定时间内一直 FindWindow 如果非 0 立即返回,到达指定时间后返回 0。

[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpszClass, string lpszWindow);

public static IntPtr FindWindowTimeout(string lpszClass, string lpszWindow, int timeout)
{
    var timeoutMonitor = new TimeoutMonitor(timeout);
    while (!timeoutMonitor.IsCompleted)
    {
        var hWnd = FindWindow(lpszClass, lpszWindow);
        if (hWnd != IntPtr.Zero) return hWnd;
    }
    return IntPtr.Zero;
}

等待文件完全写入

var fi = new FileInfo(@"C:\1.txt");
TimeoutMonitor.ThrowIfTimeout(() => fi.Exists && fi.Length > 0, 15000, "文件不存在");
var s = File.ReadAllText(fi.FullName);

等待窗口关闭

const int WM_CLOSE = 0x0010;

[DllImport("user32.dll")]
static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

[DllImport("user32.dll")]
static extern bool IsWindow(IntPtr hWnd);

public static bool WaitCloseWindow(IntPtr hWnd, int timeout)
{
    SendMessage(hWnd, WM_CLOSE, 0, 0);
    return TimeoutMonitor.WaitTimeout(() => !IsWindow(hWnd), timeout);
}

标签:string,int,等待,timeout,hWnd,超时,方法,public
From: https://www.cnblogs.com/dao/p/16608192.html

相关文章

  • jQuery on()方法示例及jquery on()方法的优点
    https://www.jb51.net/article/71614.htm#jQueryon()方法是官方推荐的绑定事件的一个方法。1$(selector).on(event,childSelector,data,function,map)......
  • js里面的三种注释方法
    https://www.cnblogs.com/rubylouvre/p/3649999.htmljavascript(js)语言里面的注释方法有三种。第一种是多行注释"/**/",一般js文件开头,介绍作者,函数等信息。/......
  • 不常见但很有用的chrome调试工具使用方法
     https://www.cnblogs.com/xiaohuochai/p/6344886.html前面的话  对于chrome调试工具,常用的是elements标签、console标签、sources标签和network标签。但实际上,还......
  • 如何将一个div水平垂直居中?6种方法做推荐
    https://www.cnblogs.com/Julia-Yuan/p/6648816.html方案一:div绝对定位水平垂直居中【margin:auto实现绝对定位元素的居中】,兼容性:,IE7及之前版本不支持di......
  • 实现a标签中的各种点击(onclick)事件的方法
    https://www.cnblogs.com/pengfei25/p/6018237.html 我们常用的在a标签中有点击事件:1.ahref="javascript:js_method();"这是我们平台上常用的方法,但是这种方法在传......
  • Unity-拓展方法
    拓展方法:在不破坏原始类的情况下,添加成员方法,只能添加成员方法。一般用于向已经封装好的程序集中添加新的方法usingUnityEngine;publicclassTest:MonoBehaviour{......
  • php断点调试工具------NetBeans+Xdebug调试php方法(测试成功)
    @原文url:http://www.cnblogs.com/dcb3688/p/4608015.html@netbeans官方调试php代码说明:https://netbeans.org/kb/docs/php/debugging_zh_CN.html个人认为,对有有经验......
  • 普林斯顿微积分读本 第18章 积分的方法:第一部分
    换元法(替代法)分部积分法18.1代替法例子1\[\intx^2\cosx^3\mathrm{d}x\]要求解这样的一个积分,可以从换元开始,首先使得\(t=x^3\),这样自然而然的就可以得到\(\c......
  • 地质统计学主要方法和基本思路
    基于两点地质统计学的传统方法包括序贯高斯模拟(SGS)(Journel和Isaaks,1984年;Goovaerts,1997年;Sahimi,2011年)、序贯指标模拟(SIS)(Goovaert,1997年,Sahimi,2011年)和联合模拟方法(Goovaer......
  • 【数据库】E-R图相关知识、绘制方法及工具推荐
    一、知识1、介绍E-R图也称实体-联系图(EntityRelationshipDiagram),提供了表示实体、属性和联系的方法,用来描述现实世界的概念模型。2、组成(1)实体(Entity)-矩形标识(2)属......