在 .NET Framework 4.0 中实现方法超时控制

在 .NET Framework 4.0 中实现方法超时控制,有几种常用方案。下面介绍几种实现方式:

方案一:使用 Task + CancellationToken(推荐)

csharp 复制代码
using System;
using System.Threading;
using System.Threading.Tasks;

public class TimeoutExample
{
    public string ExecuteWithTimeout(int timeoutMs)
    {
        var cts = new CancellationTokenSource();
        var token = cts.Token;
        
        var task = Task.Factory.StartNew(() =>
        {
            // 在子方法中需要检查 token.IsCancellationRequested
            DoWork(token);
            return "完成";
        }, token);

        // 等待任务完成或超时
        bool completed = task.Wait(timeoutMs);
        
        if (!completed)
        {
            cts.Cancel(); // 发送取消信号
            return "超时退出";
        }
        
        return task.Result;
    }

    private void DoWork(CancellationToken token)
    {
        for (int i = 0; i < 100; i++)
        {
            // 定期检查取消请求
            if (token.IsCancellationRequested)
            {
                return; // 或 throw new OperationCanceledException(token);
            }
            
            Thread.Sleep(100); // 模拟耗时操作
            SubMethod(token);  // 子方法也传递 token
        }
    }

    private void SubMethod(CancellationToken token)
    {
        token.ThrowIfCancellationRequested();
        // 执行操作...
    }
}

方案二:使用 Thread.Abort(强制终止,不推荐但有效)

csharp 复制代码
using System;
using System.Threading;

public class TimeoutWithAbort
{
    public string ExecuteWithTimeout(int timeoutMs)
    {
        string result = null;
        Exception exception = null;
        
        Thread workerThread = new Thread(() =>
        {
            try
            {
                result = DoLongRunningWork();
            }
            catch (ThreadAbortException)
            {
                Thread.ResetAbort(); // 重置中止状态
                result = "被中止";
            }
            catch (Exception ex)
            {
                exception = ex;
            }
        });

        workerThread.Start();
        
        // 等待线程完成或超时
        bool completed = workerThread.Join(timeoutMs);
        
        if (!completed)
        {
            workerThread.Abort(); // 强制终止线程
            return "超时退出";
        }

        if (exception != null)
            throw exception;
            
        return result;
    }

    private string DoLongRunningWork()
    {
        // 即使不检查任何标志,也会被 Abort 中断
        Thread.Sleep(10000);
        return "完成";
    }
}

方案三:封装成通用工具类

csharp 复制代码
using System;
using System.Threading;

public static class TimeoutHelper
{
    /// <summary>
    /// 带超时执行方法
    /// </summary>
    public static T Execute<T>(Func<T> func, int timeoutMs, T defaultValue = default(T))
    {
        T result = defaultValue;
        Exception exception = null;
        
        Thread thread = new Thread(() =>
        {
            try
            {
                result = func();
            }
            catch (ThreadAbortException)
            {
                Thread.ResetAbort();
            }
            catch (Exception ex)
            {
                exception = ex;
            }
        });

        thread.Start();
        
        if (!thread.Join(timeoutMs))
        {
            thread.Abort();
            return defaultValue;
        }

        if (exception != null)
            throw exception;
            
        return result;
    }

    /// <summary>
    /// 带超时执行无返回值方法
    /// </summary>
    public static bool Execute(Action action, int timeoutMs)
    {
        Exception exception = null;
        
        Thread thread = new Thread(() =>
        {
            try
            {
                action();
            }
            catch (ThreadAbortException)
            {
                Thread.ResetAbort();
            }
            catch (Exception ex)
            {
                exception = ex;
            }
        });

        thread.Start();
        
        if (!thread.Join(timeoutMs))
        {
            thread.Abort();
            return false; // 超时
        }

        if (exception != null)
            throw exception;
            
        return true; // 正常完成
    }
}

// 使用示例
public class Program
{
    public void Main()
    {
        // 方式1:有返回值
        var result = TimeoutHelper.Execute(() =>
        {
            Thread.Sleep(5000);
            return "完成";
        }, 2000, "超时默认值");

        // 方式2:无返回值
        bool success = TimeoutHelper.Execute(() =>
        {
            DoSomething();
        }, 3000);

        if (!success)
        {
            Console.WriteLine("操作超时");
        }
    }
    
    private void DoSomething() { }
}

方案对比

方案 优点 缺点
CancellationToken 安全、协作式取消、资源可正确释放 需要子方法配合检查 token
Thread.Abort 可强制终止,无需子方法配合 可能导致资源泄漏、状态不一致

建议

  1. 如果能控制所有子方法代码 :优先使用 CancellationToken,在关键点检查取消状态
  2. 如果调用第三方库或无法修改子方法 :使用 Thread.Abort,但要注意资源清理
  3. 对于数据库操作 :使用 SqlCommand.CommandTimeout 等内置超时机制
相关推荐
源流之道2 小时前
联想Y700 五代(TB323FU)刷 ColorOS 16 教程指南
网络·ai·刷机指南·刷机心得
优化Henry3 小时前
LTE 载波频率与频点配置详解
运维·网络·学习·5g·信息与通信
科力锐品牌君3 小时前
应用级灾备 | 海量非结构化数据如何实现高效数据保护
linux·运维·网络·安全·系统安全·数据安全·灾备
盛世宏博北京4 小时前
档案库房防护能力升级:从八防到十二防的物联网全维度感知防护体系建设方案
网络·物联网
杨福宇4 小时前
100BASE T1以太网实时控制的危机V3.21 ——辅助自动驾驶难达标
网络·网络协议·安全·自动驾驶·汽车
福建佰胜张工4 小时前
A5E00839230西门子工业核心配件详解:参数、安装调试与故障运维全攻略
运维·网络·安全·自动化
波力海苔夹心脆6755 小时前
C# 值类型与引用类型详解:存储位置、赋值机制、参数传递、相等比较、装箱拆箱与常见陷阱
开发语言·jvm·经验分享·笔记·c#·.net
蜗牛互联网5 小时前
WSL Containers GA:本地AI容器的生命周期、网络与治理验收
java·网络·人工智能·后端
红姐跨境书7 小时前
如何利用AI提升YouTube内容创作与运营效率
网络
别动我齐刘海7 小时前
简历技术栈全面复习——UDP / TCP / CAN / ZMQ / Protobuf 通信工程
网络·c++·python·tcp/ip·机器学习·udp·github