本文介绍了为什么GetThreadTimes返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我试图测量花在一个线程中用于进度报告的时间,但我从GetThreadTimes系统调用得到非常奇怪的结果。给定以下程序(在VS 2013中编译,针对.NET 4.5): using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; 命名空间ThreadTimingTest {类程序 { static Stopwatch _wallClockTimer; static System.Timers.Timer _timer = new System.Timers.Timer(); private static线程_thread; private static IntPtr _threadHandle; static void Main(string [] args) { _timer = new System.Timers.Timer(); _timer.Elapsed + =(s,e)=> { System.Runtime.InteropServices.ComTypes.FILETIME start,end,rawKernelTime,rawUserTime; GetThreadTimes(_threadHandle,out start,out end,out rawKernelTime,out rawUserTime); // ref:http://stackoverflow.com/a/6083846 ulong uLow =(ulong)rawKernelTime.dwLowDateTime; ulong uHigh =(uint)rawKernelTime.dwHighDateTime; uHigh = uHigh<< 32; long kernelTime =(long)(uHigh | uLow); uLow =(ulong)rawUserTime.dwLowDateTime; uHigh =(uint)rawUserTime.dwHighDateTime; uHigh = uHigh<< 32; long userTime =(long)(uHigh | uLow); Debug.WriteLine(Kernel time:+ kernelTime); Debug.WriteLine(User time:+ userTime); Debug.WriteLine(Combined raw execution time:+(kernelTime + userTime)); long elapsedMilliseconds =(kernelTime + userTime)/ 10000; // convert to milliseconds:raw timing unit is 100 nanoseconds Debug.WriteLine(Elapsed thread time:+ elapsedMilliseconds +milliseconds); Debug.WriteLine(Wall Clock Time:+ _wallClockTimer.ElapsedMilliseconds +milliseconds); }; _timer.Interval = 1000; _wallClockTimer = new Stopwatch(); Debug.WriteLine(Starting ...); RunTest(); Debug.WriteLine(Ended。); } public static void RunTest() { _thread = new Thread (()=> { _threadHandle = GetCurrentThread(); 秒表sw = Stopwatch.StartNew(); while(sw.ElapsedMilliseconds { int i = 1 + 2; } //做繁忙工作3秒钟 sw.Stop(); } ); _timer.Start(); _thread.Start(); a _wallClockTimer.Start(); _thread.Join(); } [DllImport(kernel32.dll,SetLastError = true)] static extern bool GetThreadTimes(IntPtr hThread, out System.Runtime.InteropServices。 ComTypes.FILETIME lpCreationTime,out System.Runtime.InteropServices.ComTypes.FILETIME lpExitTime, out System.Runtime.InteropServices.ComTypes.FILETIME lpKernelTime,out System.Runtime.InteropServices.ComTypes.FILETIME lpUserTime); [DllImport(kernel32.dll)] private static extern IntPtr GetCurrentThread(); } } 我得到以下输出: 正在启动... 内核时间:0 用户时间:0 组合原始执行时间:0 经过的线程时间:0毫秒挂钟时间:1036毫秒内核时间:0 用户时间:0 组合的原始执行时间:0 线程时间:0毫秒挂钟时间:2036毫秒线程'< No Name>'(0x191c)已退出代码0(0x0)。 已结束。 我会期望 GetThreadTimes 解决方案根据链接对你的代码进行几个简单的mod后, $ b 添加一些interop声明: c $ c> [DllImport(kernel32.dll,SetLastError = true)] [return:MarshalAs(UnmanagedType.Bool)] static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, IntPtr hSourceHandle ,IntPtr hTargetProcessHandle,out IntPtr lpTargetHandle, uint dwDesiredAccess,[MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,uint dwOptions); [Flags] public enum DuplicateOptions:uint { DUPLICATE_CLOSE_SOURCE =(0x00000001),//关闭源句柄。无论返回的任何错误状态如何,都会发生此错误。 DUPLICATE_SAME_ACCESS =(0x00000002),//忽略dwDesiredAccess参数。重复句柄具有与源句柄相同的访问权限。 } [DllImport(kernel32.dll)] static extern IntPtr GetCurrentProcess(); 然后修改句柄的分配方式: // _ threadHandle = GetCurrentThread(); IntPtr processHandle = GetCurrentProcess(); bool result = DuplicateHandle(processHandle,GetCurrentThread(),processHandle,out _threadHandle,0,false,(uint)DuplicateOptions.DUPLICATE_SAME_ACCESS); 会产生以下结果: 正在启动... 内核时间:0 用户时间:10000000 组合原始执行时间:10000000 经过的线程时间:1000毫秒挂钟时间:1006毫秒内核时间:0 用户时间:20000000 组合原始执行时间:20000000 经过的线程时间:2000毫秒 Wall Clock时间:2004毫秒内核时间:0 用户时间:30000000 组合原始执行时间:30000000 结束。 已过时的线程时间:3000毫秒挂钟时间:3045毫秒 : 最近,为处理为给定系统创建的线程太多而付出了大量的努力。假设你有一个四核处理器,20多个线程都想运行。线程对于启动,内核管理,存储器(它们具有它们自己的堆栈)等具有相当大的成本。与如果要减少线程计数相比,系统实际上可能更慢(杂乱上下文和调度)。因此,在.NET中,像 TPL (允许开发人员管理任务,而不是线程)。这允许CLR平衡适当的线程计数到目标系统。但在你的情况下(你明确创建一个托管线程),几乎总是与本机线程一对一的关系。 希望这有助于。 I'm attempting to measure the time spent in a thread for progress reporting purposes, but I'm getting very strange results from from the GetThreadTimes system call. Given the following program (compiled in VS 2013, targeting .NET 4.5):using System;using System.Diagnostics;using System.Runtime.InteropServices;using System.Threading;namespace ThreadTimingTest{ class Program { static Stopwatch _wallClockTimer; static System.Timers.Timer _timer = new System.Timers.Timer(); private static Thread _thread; private static IntPtr _threadHandle; static void Main(string[] args) { _timer = new System.Timers.Timer(); _timer.Elapsed += (s, e) => { System.Runtime.InteropServices.ComTypes.FILETIME start, end, rawKernelTime, rawUserTime; GetThreadTimes(_threadHandle, out start, out end, out rawKernelTime, out rawUserTime); //ref: http://stackoverflow.com/a/6083846 ulong uLow = (ulong)rawKernelTime.dwLowDateTime; ulong uHigh = (uint)rawKernelTime.dwHighDateTime; uHigh = uHigh << 32; long kernelTime = (long)(uHigh | uLow); uLow = (ulong)rawUserTime.dwLowDateTime; uHigh = (uint)rawUserTime.dwHighDateTime; uHigh = uHigh << 32; long userTime = (long)(uHigh | uLow); Debug.WriteLine("Kernel time: " + kernelTime); Debug.WriteLine("User time: " + userTime); Debug.WriteLine("Combined raw execution time: " + (kernelTime + userTime)); long elapsedMilliseconds = (kernelTime + userTime) / 10000; //convert to milliseconds: raw timing unit is 100 nanoseconds Debug.WriteLine("Elapsed thread time: " + elapsedMilliseconds + " milliseconds"); Debug.WriteLine("Wall Clock Time: " + _wallClockTimer.ElapsedMilliseconds + " milliseconds"); }; _timer.Interval = 1000; _wallClockTimer = new Stopwatch(); Debug.WriteLine("Starting..."); RunTest(); Debug.WriteLine("Ended."); } public static void RunTest() { _thread = new Thread ( () => { _threadHandle = GetCurrentThread(); Stopwatch sw = Stopwatch.StartNew(); while (sw.ElapsedMilliseconds < 3000) { int i = 1 + 2; } //do busy-work for 3 seconds sw.Stop(); } ); _timer.Start(); _thread.Start();a _wallClockTimer.Start(); _thread.Join(); } [DllImport("kernel32.dll", SetLastError = true)] static extern bool GetThreadTimes(IntPtr hThread, out System.Runtime.InteropServices.ComTypes.FILETIME lpCreationTime, out System.Runtime.InteropServices.ComTypes.FILETIME lpExitTime, out System.Runtime.InteropServices.ComTypes.FILETIME lpKernelTime, out System.Runtime.InteropServices.ComTypes.FILETIME lpUserTime); [DllImport("kernel32.dll")] private static extern IntPtr GetCurrentThread(); }}I get the following output:Starting...Kernel time: 0User time: 0Combined raw execution time: 0Elapsed thread time: 0 millisecondsWall Clock Time: 1036 millisecondsKernel time: 0User time: 0Combined raw execution time: 0Elapsed thread time: 0 millisecondsWall Clock Time: 2036 millisecondsThe thread '<No Name>' (0x191c) has exited with code 0 (0x0).Ended.I would expect GetThreadTimes to report something other than zero for the thread times: why is zero reported? 解决方案 After making a couple simple mods to your code based on the link provided by Hans, valid times are displayed.Adding a few interop declarations:[DllImport("kernel32.dll", SetLastError = true)][return: MarshalAs(UnmanagedType.Bool)]static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle, uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);[Flags]public enum DuplicateOptions : uint{ DUPLICATE_CLOSE_SOURCE = (0x00000001), // Closes the source handle. This occurs regardless of any error status returned. DUPLICATE_SAME_ACCESS = (0x00000002), // Ignores the dwDesiredAccess parameter. The duplicate handle has the same access as the source handle.}[DllImport("kernel32.dll")]static extern IntPtr GetCurrentProcess();then modifying how the handle is assigned://_threadHandle = GetCurrentThread(); <-- previous assignmentIntPtr processHandle = GetCurrentProcess();bool result = DuplicateHandle(processHandle, GetCurrentThread(), processHandle, out _threadHandle, 0, false, (uint) DuplicateOptions.DUPLICATE_SAME_ACCESS);produces the following result:Starting...Kernel time: 0User time: 10000000Combined raw execution time: 10000000Elapsed thread time: 1000 millisecondsWall Clock Time: 1006 millisecondsKernel time: 0User time: 20000000Combined raw execution time: 20000000Elapsed thread time: 2000 millisecondsWall Clock Time: 2004 millisecondsKernel time: 0User time: 30000000Combined raw execution time: 30000000Ended.Elapsed thread time: 3000 millisecondsWall Clock Time: 3045 millisecondsEDIT:Recently a great deal of effort has been given to handling too many threads that are created for a given system. Let's say you have a quad processor, and 20+ threads all want to run. Threads have a fairly large cost with respect to startup, kernel management, memory (they have their own stack), etc. The system may actually be slower (juggling contexts and scheduling) than if the thread count were to be reduced. So in .NET, libraries like TPL were created (allowing the developer to manage tasks, not threads). This allows the CLR to balance the appropriate thread count to the target system. But in your case (where you explicitly create a managed thread), there is nearly always a 1 to 1 relationship with native threads.Hope this helps. 这篇关于为什么GetThreadTimes返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!