Sehr schlechte Leistung von asynchronen Tasks, die in Threadpool in .Net native ausgeführt werden

Ich habe einen merkwürdigen Unterschied zwischen verwaltetem und nativem .Net-Code festgestellt. Ich habe einen schweren Job zu Threadpool umgeleitet. Wenn die App in verwaltetem Code ausgeführt wird, funktioniert alles reibungslos, aber sobald ich die native Kompilierung einschalte, wird die Aufgabe einige Male langsamer und so langsam ausgeführt, dass der UI-Thread hängen bleibt (ich denke, die CPU ist so überlastet).

Hier sind zwei Screenshots aus der Debug-Ausgabe, der linke Screenshot stammt aus verwaltetem Code und der rechte aus der nativen Kompilierung. Wie Sie sehen, ist der Zeitaufwand für UI-Tasks in beiden Fällen nahezu gleich, bis zu dem Zeitpunkt, an dem der Threadpool-Job gestartet wird. In der verwalteten Version nimmt die abgelaufene Zeit der Benutzeroberfläche zu (die Benutzeroberfläche wird blockiert und Sie können keine Maßnahmen ergreifen). Timings von Threadpool-Jobs sprechen für sich.

Der Beispielcode, um das Problem zu reproduzieren:

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");
}

Wenn Sie eine vollständige Probe benötigen - dann können Siehier herunterlade.

Wie ich getestet habe, wird der Unterschied sowohl für optimierten als auch für nicht optimierten Code in Debug- und Release-Versionen angezeigt.

Hat jemand eine Idee, was das Problem verursachen kann?

Antworten auf die Frage(2)

Ihre Antwort auf die Frage