ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

为方法增加一个超时等待

2022-08-20 17:32:51  阅读:124  来源: 互联网

标签: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
来源: https://www.cnblogs.com/dao/p/16608192.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有