Wanneer gebeurt het invoegen van een taak?

Na het lezen van de inlining in de TPL van bronnen zoals hier , Ik kreeg de indruk dat een aanroep van Task.Wait() een taak start die nog niet is begonnen (in ieder geval met behulp van de standaardplanner). Echter, het schrijven van een snelle demo zoals:

var taskB = new Task(
 () =>
      {
        Console.WriteLine("In TaskB");
        System.Threading.Thread.Sleep(5000);
        Console.WriteLine("Leaving TaskB");
      });

var taskA = new Task(
 () =>
      {
        Console.WriteLine("In TaskA");
        System.Threading.Thread.Sleep(500);
        Console.WriteLine("Waiting on TaskB");
        taskB.Wait();
        Console.WriteLine("Leaving TaskA");
        });

taskA.Start();
taskA.Wait();

Veroorzaakt een impasse. TaskA krijgt de taakB.Wait() -regel, maar taakB is nooit gestart. Ik heb niets gemompeld met de planner of zo, dus ik weet niet echt waarom de aanroep van .Wait() op taskB niet zou veroorzaken dat deze start.

4
Er is geen aanroep van taskB.Start() in uw voorbeeldcode.
toegevoegd de auteur Sean U, de bron

2 antwoord

Wait() does not cause a task to Start(). If you call Wait() on an unstarted task, it will wait for it to begin and complete until it completes, the wait timed out or the wait is cancelled. Since your call to Wait() does not contain a cancellation token or timeout, it's an infinite for the task to complete.

Ik denk dat wat je uit de blog verwart, deze regel is:

Als het echter nog niet is gestart, kan Wacht tot het kan worden voltooid   doeltaak uit de planner waar deze in de wachtrij stond en wordt uitgevoerd   het is inline op de huidige thread.

De sleutel hier is de uitdrukking "is niet begonnen met uitvoeren". Dit betekent niet dat Start() niet is aangeroepen, maar dat Start() is genoemd, waarmee de taak wordt gepland en gereedgemaakt voor uitvoeren, maar de taak is nog niet begonnen.

Start() is necessary to schedule a task for execution, it doesn't immediately begin execution. That's the main point of that blurb. If the task is ready to go but not scheduled, it may be inlined. But it won't start a task that hasn't even been scheduled.

Als u TaskStatus in MSDN bekijkt ( Zie hier ) ziet u de volgende waarden:

  • Gemaakt
  • WaitingForActivation
  • WaitingToRun
  • Running
  • WaitingForChildrenToComplete
  • RanToCompletion
  • Geannuleerd
  • Open zones

Wanneer u de taak maakt (met nieuwe of in de fabriek), bevindt deze zich in de status Gemaakt . In deze toestand gebeurt er niets met een taak. Als het eenmaal is gestart, gaat het naar WaitingForActivation en zo verder, op dit punt totdat het Running bereikt, is het volgens die blog mogelijk dat het kan worden geïnterlinieerd.

Dus, lang verhaal kort, het maken van een taak plaatst hem gewoon in de aangemaakte status en zal het niet starten als Wait() wordt aangeroepen. Heb je zin?

15
toegevoegd

De in dat artikel genoemde inlining is anders dan een taakstart. Wachten op een taak start niet - wat heel gemakkelijk kan worden aangetoond. Probeer gewoon het volgende:

namespace Test
{
    using System;
    using System.Threading.Tasks;

    internal class TestCompile
    {
        private static void Main(string[] args)
        {
            Task t = new Task(() => Console.WriteLine("Executed!"));
            t.Wait(5000);
            Console.WriteLine("After wait...");
            Console.ReadKey();
        }
    }
}

Je zult zien dat de taak nooit begint ...

Een aanroep van task.Wait() start een taak niet. Hierdoor wordt de taak onmiddellijk uitgevoerd en "inline" op de huidige thread (met de standaardplanner) als:

  • De taak is gestart, maar ...
  • De taak wordt momenteel niet uitgevoerd (omdat Taken in de wachtrij worden geplaatst door de planner)
  • De planner van de taak (gemaakt tijdens de constructie) is dezelfde planner als de huidige
  • De taak is niet geannuleerd
  • Er is niets aan de taak te wijten

Het derde punt daar is fuzzy - het kan inline op een andere scheduler uitvoeren, maar dit vereist dat de andere scheduler het onmiddellijk kan uitvoeren, dus het is afhankelijk van de scheduler die dit ondersteunt.

2
toegevoegd