我发现了托管代码和 .Net Native 代码之间的一个奇怪差异。我有一个严重的作业被重定向到线程池。在托管代码中运行应用程序时,一切都很顺利,但是一旦我切换到本地编译,任务运行速度变慢了几倍,以至于它会挂起UI线程(我猜CPU过载了)。下面是来自调试输出的两个截图,左边的是托管代码,右边的是本地编译。您可以看到在两种情况下UI任务消耗的时间几乎相同,直到线程池作业开始的时间为止-然后在托管版本中,UI经过时间增加(实际上UI被阻塞,您无法采取任何行动)。线程池作业的计时说明了问题所在。
复现问题的示例代码:
private int max = 2000;
private async void UIJob_Click(object sender, RoutedEventArgs e)
{
IProgress<int> progress = new Progress<int>((p) => { MyProgressBar.Value = (double)p / max; });
await Task.Run(async () => { await SomeUIJob(progress); });
}
private async Task SomeUIJob(IProgress<int> progress)
{
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < max; i++)
{
if (i % 100 == 0) { Debug.WriteLine($" UI time elapsed => {watch.ElapsedMilliseconds}"); watch.Restart(); }
await Task.Delay(1);
progress.Report(i);
}
}
private async void ThreadpoolJob_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Firing on Threadpool");
await Task.Run(() =>
{
double a = 0.314;
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 50000000; i++)
{
a = Math.Sqrt(a) + Math.Sqrt(a + 1) + i;
if (i % 10000000 == 0) { Debug.WriteLine($"Threadpool -> a value = {a} got in {watch.ElapsedMilliseconds} ms"); watch.Restart(); };
}
});
Debug.WriteLine("Finished with Threadpool");
}
如果您需要完整的示例-那么您可以在这里下载。我已经测试了优化和未优化的代码,无论是Debug版还是Release版都存在差异。
有人知道是什么原因导致了这个问题吗?
ThreadPool.SetMinThreads/SetMaxThreads
吗? - noseratio - open to work