You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多线程与优先级调整:用Stopwatch统计线程耗时并找最短耗时线程

线程执行时间统计与最短耗时线程查找方案

嘿,你的思路其实没问题——用Stopwatch来统计线程执行时间是完全可行的,不过我们可以优化一下实现方式,让结果统计和线程管理更清晰。另外你提到C/C++里的GetThreadTimes,.NET里也有对应的方案,我来给你详细梳理下:

完整可运行的实现示例

我们可以把每个线程的计时结果统一存储起来,等所有线程都执行完毕后,再统计找出耗时最短的那个:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Diagnostics;

class ThreadTimingDemo
{
    // 用来存每个线程的名称和对应的耗时
    private static readonly Dictionary<string, TimeSpan> _threadExecutionTimes = new Dictionary<string, TimeSpan>();
    private static readonly object _lockObj = new object();

    static void Main()
    {
        // 创建线程的时候给个名称,后面统计的时候好识别
        Thread t1 = new Thread(FirstThread) { Name = "FirstThread" };
        Thread t2 = new Thread(SecondThread) { Name = "SecondThread" };
        Thread t3 = new Thread(ThirdThread) { Name = "ThirdThread" };

        // 启动所有线程
        t1.Start();
        t2.Start();
        t3.Start();

        // 必须等所有线程都跑完再统计,不然会拿到不完整的结果
        t1.Join();
        t2.Join();
        t3.Join();

        // 先输出所有线程的耗时
        Console.WriteLine("各线程执行耗时:");
        foreach (var kvp in _threadExecutionTimes)
        {
            Console.WriteLine($"{kvp.Key}: {kvp.Value.TotalMilliseconds:F2} ms");
        }

        // 找出耗时最短的线程
        var fastestThread = _threadExecutionTimes.OrderBy(kvp => kvp.Value).First();
        Console.WriteLine($"\n耗时最短的线程是:{fastestThread.Key},耗时 {fastestThread.Value.TotalMilliseconds:F2} ms");
    }

    static void FirstThread()
    {
        Stopwatch stopwatch = Stopwatch.StartNew();
        try
        {
            // 模拟你的业务逻辑:计算1到10000的和
            Enumerable.Range(1, 10000).Select(x => x).Sum();
        }
        finally
        {
            stopwatch.Stop();
            // 多个线程同时写字典会出问题,所以加个锁保证线程安全
            lock (_lockObj)
            {
                _threadExecutionTimes[Thread.CurrentThread.Name] = stopwatch.Elapsed;
            }
        }
    }

    static void SecondThread()
    {
        Stopwatch stopwatch = Stopwatch.StartNew();
        try
        {
            // 模拟另一种业务场景:字符串拼接操作
            string result = string.Empty;
            for (int i = 0; i < 10000; i++)
            {
                result += i.ToString();
            }
        }
        finally
        {
            stopwatch.Stop();
            lock (_lockObj)
            {
                _threadExecutionTimes[Thread.CurrentThread.Name] = stopwatch.Elapsed;
            }
        }
    }

    static void ThirdThread()
    {
        Stopwatch stopwatch = Stopwatch.StartNew();
        try
        {
            // 模拟IO密集型操作(用Sleep代替实际的IO等待)
            Thread.Sleep(100);
        }
        finally
        {
            stopwatch.Stop();
            lock (_lockObj)
            {
                _threadExecutionTimes[Thread.CurrentThread.Name] = stopwatch.Elapsed;
            }
        }
    }
}

几点要注意的地方

  • 线程安全的结果存储:因为多个线程会同时往_threadExecutionTimes字典里写数据,必须用lock来保证线程安全,不然很容易出现并发异常或者数据错乱。
  • 等待线程执行完成:一定要用Thread.Join()等所有线程都跑完再统计结果,不然可能会出现部分线程还在运行,统计结果不完整的情况。
  • Stopwatch的优势:Stopwatch是基于系统高精度计时器实现的,对于测量代码段的执行时间非常精准,完全能满足你的需求。

关于.NET中类似GetThreadTimes的方法

如果你需要获取线程的内核态/用户态CPU时间(就像C/C++里的GetThreadTimes那样),.NET里可以用ProcessThread类来实现:

// 获取当前线程对应的ProcessThread实例
ProcessThread currentThread = Process.GetCurrentProcess().Threads.Cast<ProcessThread>()
    .First(t => t.Id == Thread.CurrentThread.ManagedThreadId);

// 获取线程的用户态CPU时间和内核态CPU时间
TimeSpan userTime = currentThread.UserProcessorTime;
TimeSpan kernelTime = currentThread.PrivilegedProcessorTime;

不过要注意,ProcessThread获取的是线程从启动到当前的累计CPU时间,如果你只是想测量特定代码段的执行时间,Stopwatch还是更直接、更合适的选择。

内容的提问来源于stack exchange,提问作者Romazes88

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:41:19