Я пытаюсь измерить время, проведенное в потоке, для целей отчета о проделанной работе, но я получаю очень странные результаты из системного вызова GetThreadTimes. Учитывая следующую программу (скомпилированную в VS 2013, таргетирования .NET 4.5):Почему GetThreadTimes возвращается
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();
}
}
Я получаю следующий вывод:
Starting...
Kernel time: 0
User time: 0
Combined raw execution time: 0
Elapsed thread time: 0 milliseconds
Wall Clock Time: 1036 milliseconds
Kernel time: 0
User time: 0
Combined raw execution time: 0
Elapsed thread time: 0 milliseconds
Wall Clock Time: 2036 milliseconds
The thread '<No Name>' (0x191c) has exited with code 0 (0x0).
Ended.
Я ожидал бы GetThreadTimes
, чтобы сообщить что-то, отличное от нуля в течение времени резьбы : почему ноль сообщается?
[Несколько управляемых потоков могут работать в одном и том же потоке ОС] (http://msdn.microsoft.com/en-us/library/74169f59.aspx). Гипотеза: среда выполнения .NET прерывает поток ОС до того, как закончит свой временной срез, и поэтому его время не записывается (см. Статью [this] (http://blog.kalmbachnet.de/?postid=28)). Конечно, времена не были бы точными, так как вы не измеряете время, затраченное на поток * managed *, вы измеряете основной поток ОС. – Blorgbeard
Поскольку GetCurrentThread() не возвращает то, что, по вашему мнению, он делает. Задание времени для неправильной нити. Недавно было описано в [этом сообщении блога] (http://blogs.msdn.com/b/oldnewthing/archive/2014/10/15/10564700.aspx). –