Návod: Ladění paralelní aplikace v sadě Visual Studio (C#, Visual Basic, C++)

Tento návod ukazuje, jak pomocí oken Paralelní úlohy a Paralelní zásobníky ladit paralelní aplikaci. Tato okna vám pomůžou pochopit a ověřit chování kódu za běhu, který používá knihovnu TPL (Task Parallel Library) nebo Concurrency Runtime. Tento názorný postup obsahuje ukázkový kód, který obsahuje předdefinované zarážky. Po přerušení kódu názorný postup ukazuje, jak pomocí oken Paralelní úlohy a Paralelní zásobníky prozkoumat.

V tomto názorném postupu se naučíte tyto úlohy:

  • Jak zobrazit zásobníky volání všech vláken v jednom zobrazení.

  • Jak zobrazit seznam instancí vytvořených System.Threading.Tasks.Task ve vaší aplikaci

  • Zobrazení skutečných zásobníků volání úloh místo vláken

  • Jak přejít na kód z oken Paralelní úlohy a Paralelní zásobníky

  • Jak se okna vyrovnávají se škálováním prostřednictvím seskupení, přiblížení a dalších souvisejících funkcí.

Požadavky

V tomto názorném postupu se předpokládá, že je povolená jenom my code (ve výchozím nastavení je povolená v novějších verzích sady Visual Studio). V nabídce Nástroje vyberte Možnosti, rozbalte uzel Ladění, vyberte Obecné a pak vyberte Povolit pouze můj kód (pouze spravované). Pokud tuto funkci nenastavíte, můžete tento názorný postup použít, ale výsledky se můžou lišit od ilustrací.

Ukázka v jazyce C#

Pokud použijete ukázku jazyka C#, předpokládá se také, že externí kód je skrytý. Pokud chcete přepnout, jestli se zobrazí externí kód, klikněte pravým tlačítkem myši na záhlaví tabulky Název okna Zásobník volání a pak vyberte nebo zrušte zaškrtnutí políčka Zobrazit externí kód. Pokud tuto funkci nenastavíte, můžete tento názorný postup použít, ale výsledky se můžou lišit od ilustrací.

Ukázka jazyka C++

Pokud použijete ukázku jazyka C++, můžete ignorovat odkazy na externí kód v tomto článku. Externí kód se vztahuje pouze na ukázku jazyka C#.

Ilustrace

Ilustrace v tomto článku jsou zaznamenány na čtyřjádrový počítač se spuštěnou ukázkou jazyka C#. I když k dokončení tohoto návodu můžete použít jiné konfigurace, můžou se ilustrace lišit od toho, co se zobrazuje na vašem počítači.

Vytvoření ukázkového projektu

Vzorový kód v tomto názorném postupu je určen pro aplikaci, která nic nedělá. Účelem tohoto cvičení je pochopit, jak pomocí oken nástrojů ladit paralelní aplikaci.

  1. Otevřete Visual Studio a vytvořte nový projekt.

    Pokud úvodní okno není otevřené, zvolte Okno Start souboru>.

    V úvodním okně zvolte Nový projekt.

    V úvodním okně zvolte Vytvořit nový projekt.

    V okně Vytvořit nový projekt zadejte nebo zadejte konzolu do vyhledávacího pole. Dále v seznamu jazyků zvolte C#, C++ nebo Visual Basic a pak v seznamu Platformy zvolte Windows .

    Po použití filtrů jazyka a platformy zvolte konzolovou aplikaci pro .NET Core nebo C++ a pak zvolte Další.

    Poznámka:

    Pokud nevidíte správnou šablonu, přejděte do části Nástroje Získat nástroje>a funkce..., čímž se otevře Instalační program pro Visual Studio. Zvolte vývoj desktopových aplikací .NET nebo vývoj desktopových aplikací pomocí úlohy C++ a pak zvolte Upravit.

    V okně Konfigurovat nový projekt zadejte název nebo do pole Název projektu použijte výchozí název. Potom zvolte Další nebo Vytvořit podle toho, která možnost je k dispozici.

    Pro .NET Core zvolte buď doporučenou cílovou architekturu, nebo .NET 8, a pak zvolte Vytvořit.

    Zobrazí se nový projekt konzoly. Po vytvoření projektu se zobrazí zdrojový soubor.

  2. V projektu otevřete soubor kódu .cpp, .cs nebo .vb. Odstraňte jeho obsah a vytvořte prázdný soubor kódu.

  3. Do prázdného souboru kódu vložte následující kód pro vybraný jazyk.

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Diagnostics;
    
    class S
    {
      static void Main()
      {
        pcount = Environment.ProcessorCount;
        Console.WriteLine("Proc count = " + pcount);
        ThreadPool.SetMinThreads(4, -1);
        ThreadPool.SetMaxThreads(4, -1);
    
        t1 = new Task(A, 1);
        t2 = new Task(A, 2);
        t3 = new Task(A, 3);
        t4 = new Task(A, 4);
        Console.WriteLine("Starting t1 " + t1.Id.ToString());
        t1.Start();
        Console.WriteLine("Starting t2 " + t2.Id.ToString());
        t2.Start();
        Console.WriteLine("Starting t3 " + t3.Id.ToString());
        t3.Start();
        Console.WriteLine("Starting t4 " + t4.Id.ToString());
        t4.Start();
    
        Console.ReadLine();
      }
    
      static void A(object o)
      {
        B(o);
      }
      static void B(object o)
      {
        C(o);
      }
      static void C(object o)
      {
        int temp = (int)o;
    
        Interlocked.Increment(ref aa);
        while (aa < 4)
        {
          ;
        }
    
        if (temp == 1)
        {
          // BP1 - all tasks in C
          Debugger.Break();
          waitFor1 = false;
        }
        else
        {
          while (waitFor1)
          {
            ;
          }
        }
        switch (temp)
        {
          case 1:
            D(o);
            break;
          case 2:
            F(o);
            break;
          case 3:
          case 4:
            I(o);
            break;
          default:
            Debug.Assert(false, "fool");
            break;
        }
      }
      static void D(object o)
      {
        E(o);
      }
      static void E(object o)
      {
        // break here at the same time as H and K
        while (bb < 2)
        {
          ;
        }
        //BP2 - 1 in E, 2 in H, 3 in J, 4 in K
        Debugger.Break();
        Interlocked.Increment(ref bb);
    
        //after
        L(o);
      }
      static void F(object o)
      {
        G(o);
      }
      static void G(object o)
      {
        H(o);
      }
      static void H(object o)
      {
        // break here at the same time as E and K
        Interlocked.Increment(ref bb);
        Monitor.Enter(mylock);
        while (bb < 3)
        {
          ;
        }
        Monitor.Exit(mylock);
    
    
        //after
        L(o);
      }
      static void I(object o)
      {
        J(o);
      }
      static void J(object o)
      {
        int temp2 = (int)o;
    
        switch (temp2)
        {
          case 3:
            t4.Wait();
            break;
          case 4:
            K(o);
            break;
          default:
            Debug.Assert(false, "fool2");
            break;
        }
      }
      static void K(object o)
      {
        // break here at the same time as E and H
        Interlocked.Increment(ref bb);
        Monitor.Enter(mylock);
        while (bb < 3)
        {
          ;
        }
        Monitor.Exit(mylock);
    
    
        //after
        L(o);
      }
      static void L(object oo)
      {
        int temp3 = (int)oo;
    
        switch (temp3)
        {
          case 1:
            M(oo);
            break;
          case 2:
            N(oo);
            break;
          case 4:
            O(oo);
            break;
          default:
            Debug.Assert(false, "fool3");
            break;
        }
      }
      static void M(object o)
      {
        // breaks here at the same time as N and Q
        Interlocked.Increment(ref cc);
        while (cc < 3)
        {
          ;
        }
        //BP3 - 1 in M, 2 in N, 3 still in J, 4 in O, 5 in Q
        Debugger.Break();
        Interlocked.Increment(ref cc);
        while (true)
          Thread.Sleep(500); // for ever
      }
      static void N(object o)
      {
        // breaks here at the same time as M and Q
        Interlocked.Increment(ref cc);
        while (cc < 4)
        {
          ;
        }
        R(o);
      }
      static void O(object o)
      {
        Task t5 = Task.Factory.StartNew(P, TaskCreationOptions.AttachedToParent);
        t5.Wait();
        R(o);
      }
      static void P()
      {
        Console.WriteLine("t5 runs " + Task.CurrentId.ToString());
        Q();
      }
      static void Q()
      {
        // breaks here at the same time as N and M
        Interlocked.Increment(ref cc);
        while (cc < 4)
        {
          ;
        }
        // task 5 dies here freeing task 4 (its parent)
        Console.WriteLine("t5 dies " + Task.CurrentId.ToString());
        waitFor5 = false;
      }
      static void R(object o)
      {
        if ((int)o == 2)
        {
          //wait for task5 to die
          while (waitFor5) { ;}
    
    
          int i;
          //spin up all procs
          for (i = 0; i < pcount - 4; i++)
          {
            Task t = Task.Factory.StartNew(() => { while (true);});
            Console.WriteLine("Started task " + t.Id.ToString());
          }
    
          Task.Factory.StartNew(T, i + 1 + 5, TaskCreationOptions.AttachedToParent); //scheduled
          Task.Factory.StartNew(T, i + 2 + 5, TaskCreationOptions.AttachedToParent); //scheduled
          Task.Factory.StartNew(T, i + 3 + 5, TaskCreationOptions.AttachedToParent); //scheduled
          Task.Factory.StartNew(T, i + 4 + 5, TaskCreationOptions.AttachedToParent); //scheduled
          Task.Factory.StartNew(T, (i + 5 + 5).ToString(), TaskCreationOptions.AttachedToParent); //scheduled
    
          //BP4 - 1 in M, 2 in R, 3 in J, 4 in R, 5 died
          Debugger.Break();
        }
        else
        {
          Debug.Assert((int)o == 4);
          t3.Wait();
        }
      }
      static void T(object o)
      {
        Console.WriteLine("Scheduled run " + Task.CurrentId.ToString());
      }
      static Task t1, t2, t3, t4;
      static int aa = 0;
      static int bb = 0;
      static int cc = 0;
      static bool waitFor1 = true;
      static bool waitFor5 = true;
      static int pcount;
      static S mylock = new S();
    }
    

Po aktualizaci souboru kódu uložte změny a sestavte řešení.

  1. V nabídce File (Soubor) vyberte Save All (Uložit vše).

  2. V nabídce Sestavení vyberte Znovu sestavit řešení.

Všimněte si, že existují čtyři volání Debugger.Break (DebugBreak v ukázce jazyka C++). Proto nemusíte vkládat zarážky. Spuštění aplikace způsobí, že se v ladicím programu přeruší až čtyřikrát.

Použití okna Paralelní zásobníky: Zobrazení vláken

Začněte tak, že v nabídce Ladění vyberete Spustit ladění. Počkejte, až se dosáhne první zarážky.

Zobrazení zásobníku volání jednoho vlákna

  1. V nabídce Ladění přejděte na Windows a pak vyberte Vlákna. Ukotvení okna Vlákna v dolní části sady Visual Studio

  2. V nabídce Ladění přejděte na Windows a pak vyberte Zásobník volání. Ukotvení okna Zásobník volání v dolní části sady Visual Studio

  3. Poklikejte na vlákno v okně Vlákna , aby bylo aktuální. Aktuální vlákna mají žlutou šipku. Když změníte aktuální vlákno, jeho zásobník volání se zobrazí v okně Zásobník volání.

Prozkoumání okna Paralelní zásobníky

V nabídce Ladění přejděte na Windows a pak vyberte Paralelní zásobníky. Ujistěte se, že je v poli v levém horním rohu vybraná vlákna.

Pomocí okna Paralelní zásobníky můžete zobrazit více zásobníků volání najednou v jednom zobrazení. Následující obrázek znázorňuje okno Paralelní zásobníky nad oknem Zásobník volání.

Screenshot of Threads view in Parallel Stacks window.

Threads view in Parallel Stacks window

Zásobník volání hlavního vlákna se zobrazí v jednom poli a zásobníky volání pro ostatní čtyři vlákna jsou seskupeny do jiného pole. Čtyři vlákna jsou seskupené dohromady, protože jejich rámce zásobníku sdílejí stejné kontexty metody; to znamená, že jsou ve stejných metodách: A, Ba C. Pokud chcete zobrazit ID vláken a názvy vláken, které sdílejí stejné pole, najeďte myší na pole se záhlavím ([#] Vlákna). Aktuální vlákno se zobrazí tučně.

Screenshot of Tooltip that shows thread IDs and names.

Tooltip that shows thread IDs and names

Žlutá šipka označuje aktivní rámec zásobníku aktuálního vlákna.

Počet podrobností pro snímky zásobníku (Názvy modulů, typy parametrů, názvy parametrů, hodnoty parametrů, čísla řádků a posuny bajtů) můžete nastavit tak, že kliknete pravým tlačítkem myši v okně zásobníkuvolání.

Modré zvýraznění kolem pole označuje, že aktuální vlákno je součástí tohoto pole. Aktuální vlákno je také označeno tučným rámečkem zásobníku v popisu. Pokud dvakrát kliknete na hlavní vlákno v okně Vlákna, můžete sledovat, že šipka zvýraznění v okně Paralelní zásobníky se odpovídajícím způsobem přesune.

Screenshot of Highlighted main thread in Parallel Stacks window.

Highlighted main thread in Parallel Stacks window

Pokračovat v provádění až do druhé zarážky

Pokud chcete pokračovat v provádění, dokud se nenarazí druhá zarážka, vyberte v nabídce Ladění možnost Pokračovat. Následující obrázek znázorňuje strom vlákna na druhé zarážce.

Screenshot of Parallel Stacks window that shows many branches.

Parallel Stacks window that shows many branches

Na první zarážce byly čtyři vlákna všechna z metod S.A do S.B do S.C. Tyto informace jsou stále viditelné v okně Paralelní zásobníky , ale čtyři vlákna pokročila dále. Jeden z nich pokračoval do S.D a pak S.E. Další pokračoval ve S.F, S.G a S.H. Dva další pokračovali ve S.I a S.J a odsud jeden z nich šel do S.K a druhý pokračoval v externím kódu uživatele.

Když najedete myší na snímky zásobníku, zobrazí se ID vláken a další podrobnosti rámce. Modré zvýraznění označuje aktuální vlákno a žlutá šipka označuje aktivní rámeček zásobníku aktuálního vlákna.

Když najedete myší na záhlaví pole, například 1 vlákno nebo 2 vlákna, zobrazí se ID vláken. Když najedete myší na snímky zásobníku, zobrazí se ID vláken a další podrobnosti rámce. Modré zvýraznění označuje aktuální vlákno a žlutá šipka označuje aktivní rámeček zásobníku aktuálního vlákna.

Ikona hadrových vláken (propletené čáry) označuje aktivní rámečky zásobníku neaktuální vlákna. V okně Zásobník volání poklikejte na S.B a přepněte rámce. Okno Paralelní zásobníky označuje aktuální rámec zásobníku aktuálního vlákna pomocí ikony zakřivené šipky.

Poznámka:

Popis všech ikon v okně Paralelní zásobníky najdete v části Použití okna Paralelní zásobníky.

V okně Vlákna přepněte mezi vlákny a všimněte si, že se zobrazení v okně Paralelní zásobníky aktualizuje.

Pomocí místní nabídky v okně Paralelní zásobníky můžete přepnout na jiné vlákno nebo na jiný rámec jiného vlákna. Klikněte například pravým tlačítkem myši S.J, přejděte na přepínač Na rámeček a vyberte příkaz.

Screenshot of Parallel Stacks Path of Execution.

Parallel Stacks Path of Execution

Klikněte pravým tlačítkem myši S.C a přejděte na přepínač Na rámec. Jeden z příkazů má značku zaškrtnutí, která označuje rámec zásobníku aktuálního vlákna. Můžete přepnout na tento rámec stejného vlákna (pouze zakřivená šipka se přesune) nebo můžete přepnout na druhé vlákno (modré zvýraznění se také přesune). Následující obrázek znázorňuje podnabídku.

Screenshot of Stacks menu with 2 options on C while J is current.

Stacks menu with 2 options on C while J is current

Pokud je kontext metody přidružený pouze k jednomu rámečku zásobníku, záhlaví pole zobrazí 1 vlákno a můžete na něj přepnout poklikáním. Pokud dvakrát kliknete na kontext metody, který má přidružený více než 1 rámec, nabídka se automaticky zobrazí. Při najetí myší na kontexty metody si všimněte černého trojúhelníku vpravo. Kliknutím na tento trojúhelník se zobrazí také místní nabídka.

U velkých aplikací, které mají mnoho vláken, se můžete zaměřit jenom na podmnožinu vláken. Okno Paralelní zásobníky může zobrazovat zásobníky volání pouze pro vlákna s příznakem. Pokud chcete označit vlákna příznakem, použijte místní nabídku nebo první buňku vlákna.

Na panelu nástrojů vyberte tlačítko Zobrazit pouze příznak vedle seznamu.

Screenshot of Parallel Stacks window and tooltip.

Parallel Stacks window and tooltip

Teď se v okně Paralelní zásobníky zobrazují jenom vlákna s příznakem.

Pokračovat v provádění až do třetí zarážky

  1. Pokud chcete pokračovat v provádění, dokud se nenarazí třetí zarážka, vyberte v nabídce Ladění možnost Pokračovat.

    Pokud je více vláken ve stejné metodě, ale metoda nebyla na začátku zásobníku volání, metoda se zobrazí v různých polích. Příklad aktuální zarážky je S.L, který má tři vlákna a zobrazuje se ve třech polích. Poklikejte na S.L.

    Screenshot of Execution path in Parallel Stacks window.

    Execution path in Parallel Stacks window

    Všimněte si, že S.L je tučné písmo v dalších dvou polích, abyste viděli, kde se nachází. Pokud chcete zjistit, které rámce volají do S.L a které rámce volá, vyberte na panelu nástrojů tlačítko Přepnout zobrazení metody. Následující obrázek znázorňuje zobrazení metody okna Paralelní zásobníky .

    Screenshot of Method view in Parallel Stacks window.

    Method view in Parallel Stacks window

    Všimněte si, jak se diagram otočil na vybranou metodu a umístil ho do vlastního pole uprostřed zobrazení. Volaní a volající se zobrazí nahoře a dole. Chcete-li tento režim opustit, znovu vyberte tlačítko Přepnout zobrazení metody.

    Místní nabídka okna Paralelní zásobníky obsahuje také následující položky.

    • Šestnáctkové zobrazení přepíná čísla v popisech desetinných a šestnáctkových čísel.

    • Symbol Nastavení otevřít příslušná dialogová okna.

    • Zobrazení vláken ve zdroji přepíná zobrazení značek vláken ve zdrojovém kódu, které zobrazuje umístění vláken ve zdrojovém kódu.

    • Zobrazit externí kód zobrazí všechny rámce, i když nejsou v uživatelském kódu. Zkuste diagram rozbalit, aby se přizpůsobil ostatním snímkům (což může být neaktivní, protože pro ně nemáte symboly).

  2. V okně Paralelní zásobníky se ujistěte, že je na panelu nástrojů zapnuté tlačítko Automatické posouvání na aktuální rámec zásobníku.

    Pokud máte velké diagramy a přejdete na další zarážku, můžete chtít, aby se zobrazení automaticky posouvat na aktivní rámec zásobníku aktuálního vlákna; to znamená, že vlákno, které nejprve narazilo na zarážku.

  3. Než budete pokračovat, v okně Paralelní zásobníky se posuňte úplně doleva a úplně dolů.

Pokračovat v provádění až do čtvrté zarážky

  1. Pokud chcete pokračovat v provádění, dokud nebude nalezena čtvrtá zarážka, vyberte v nabídce Ladění možnost Pokračovat.

    Všimněte si, jak se automaticky rozbalilo zobrazení. Přepínání vláken v okně Vlákna nebo přepínání rámců zásobníku v okně Zásobník volání a všimněte si, že zobrazení se vždy automaticky zapisuje do správného rámce. Vypněte možnost Automatické posouvání na aktuální rámec nástroje a zobrazte rozdíl.

    Zobrazení ptačí perspektivy také pomáhá s velkými diagramy v okně Paralelní zásobníky . Ve výchozím nastavení je ptačí perspektiva zapnutá. Můžete ho ale přepnout kliknutím na tlačítko mezi posuvníky v pravém dolním rohu okna, jak je znázorněno na následujícím obrázku.

    Screenshot of Birds eye view in Parallel Stacks window.

    Bird's-eye view in Parallel Stacks window

    V zobrazení ptačí perspektivy můžete obdélník přesunout a rychle se posouvat kolem diagramu.

    Dalším způsobem, jak diagram přesunout v libovolném směru, je vybrat prázdnou oblast diagramu a přetáhnout ho tam, kde ho chcete.

    Pokud chcete diagram přiblížit nebo oddálit, stiskněte a podržte klávesu CTRL a pohybujte kolečkem myši. Případně vyberte tlačítko Lupa na panelu nástrojů a pak použijte nástroj Lupa.

    Zásobníky můžete zobrazit také ve směru shora dolů místo dolů, a to tak, že kliknete na nabídku Nástroje, kliknete na Možnosti a pak vyberete nebo vymažete možnost v uzlu Ladění.

  2. Než budete pokračovat, v nabídce Ladění vyberte Zastavit ladění ukončit provádění.

Použití okna Paralelní úlohy a zobrazení úkolů v okně Paralelní zásobníky

Doporučujeme, abyste před pokračováním dokončili předchozí postupy.

Restartujte aplikaci, dokud se nenarazí první zarážka:

  1. V nabídce Ladění vyberte Spustit ladění a počkejte na dosažení první zarážky.

  2. V nabídce Ladění přejděte na Windows a pak vyberte Vlákna. Ukotvení okna Vlákna v dolní části sady Visual Studio

  3. V nabídce Ladění přejděte na Windows a vyberte Zásobník volání. Ukotvení okna Zásobník volání v dolní části sady Visual Studio

  4. Poklikejte na vlákno v okně Vlákna , aby bylo aktuální. Aktuální vlákna mají žlutou šipku. Když změníte aktuální vlákno, ostatní okna se aktualizují. Dále prozkoumáme úkoly.

  5. V nabídce Ladění přejděte na Windows a pak vyberte Úkoly. Následující obrázek znázorňuje okno Úkoly .

    Screenshot of Four running tasks in Tasks window.

    Four running tasks in Tasks window

    Pro každou spuštěnou úlohu můžete přečíst jeho ID, které je vráceno stejnou pojmenovanou vlastností, ID a název vlákna, které ho spouští, jeho umístění (najeďte myší na popis, který obsahuje celý zásobník volání). Pod sloupcem Úkol můžete také zobrazit metodu, která byla předána do úkolu. Jinými slovy, výchozí bod.

    Můžete řadit libovolný sloupec. Všimněte si glyf řazení, který označuje sloupec a směr řazení. Sloupce můžete také změnit tak, že je přetáhnete doleva nebo doprava.

    Žlutá šipka označuje aktuální úkol. Úkoly můžete přepínat poklikáním na úkol nebo pomocí místní nabídky. Když přepnete úkoly, podkladové vlákno se změní na aktuální a ostatní okna se aktualizují.

    Když ručně přepnete z jednoho úkolu na jiný, obrys šipky označuje aktuální kontext ladicího programu pro neaktuální úlohu.

    Když ručně přepnete z jednoho úkolu na jiný, žlutá šipka se přesune, ale bílá šipka stále zobrazuje úkol, který způsobil přerušení ladicího programu.

Pokračovat v provádění až do druhé zarážky

Pokud chcete pokračovat v provádění, dokud se nenarazí druhá zarážka, vyberte v nabídce Ladění možnost Pokračovat.

Dříve se ve sloupci Stav zobrazily všechny úkoly jako Aktivní, ale teď jsou dva úkoly blokované. Úkoly je možné blokovat z mnoha různých důvodů. Ve sloupci Stav najeďte myší na čekající úkol, abyste se dozvěděli, proč je blokovaný. Například na následujícím obrázku čeká úkol 11 na úkolu 12.

Screenshot of Two waiting tasks in Tasks window.

Dříve se ve sloupci Stav zobrazily všechny úkoly jako Aktivní, ale teď jsou dva úkoly blokované. Úkoly je možné blokovat z mnoha různých důvodů. Ve sloupci Stav najeďte myší na čekající úkol, abyste se dozvěděli, proč je blokovaný. Například na následujícím obrázku úkol 4 čeká na úkol 5.

Two waiting tasks in Tasks window

Úkol 4 zase čeká na monitor vlastněný vláknem přiřazeným k úkolu 2. (Klikněte pravým tlačítkem myši na řádek záhlaví a zvolte Přiřazení vlákna sloupců>pro zobrazení hodnoty přiřazení vlákna pro úkol 2)

Waiting task and tooltip in Tasks window

Úkol můžete označit příznakem kliknutím na příznak v prvním sloupci okna Úkoly .

Pomocí příznaku můžete sledovat úkoly mezi různými zarážky ve stejné relaci ladění nebo filtrovat úkoly, jejichž zásobníky volání se zobrazují v okně Paralelní zásobníky .

Když jste použili okno Paralelní zásobníky dříve, zobrazili jste vlákna aplikace. Znovu si prohlédněte okno Paralelní zásobníky , ale tentokrát si prohlédněte úlohy aplikace. Uděláte to tak , že v poli vlevo nahoře vyberete Úkoly . Následující obrázek znázorňuje zobrazení Úkolů.

Screenshot of Tasks view in Parallel Stacks window.

Tasks view in Parallel Stacks window

Vlákna, která aktuálně nespouštějí úlohy, se nezobrazují v zobrazení úloh v okně Paralelní zásobníky . Pro vlákna, která provádějí úlohy, jsou některé rámce zásobníku, které nejsou relevantní pro úkoly, filtrovány z horní a dolní části zásobníku.

Znovu zobrazte okno Úkoly. Kliknutím pravým tlačítkem myši na záhlaví libovolného sloupce zobrazíte místní nabídku sloupce.

K přidání nebo odebrání sloupců můžete použít místní nabídku. Například sloupec AppDomain není vybraný; proto se v seznamu nezobrazuje. Vyberte nadřazený objekt. Sloupec Nadřazený se zobrazí bez hodnot pro některý ze čtyř úkolů.

Pokračovat v provádění až do třetí zarážky

Pokud chcete pokračovat v provádění, dokud se nenarazí třetí zarážka, vyberte v nabídce Ladění možnost Pokračovat.

Screenshot of Parent-child view in Tasks window.

V tomto příkladu spuštění si všimněte, že úloha 11 a úkol 12 běží ve stejném vlákně (pokud je skrytý sloupec Přiřazení vlákna). Tyto informace se nezobrazují v okně Vlákna . Tady je další výhoda okna Úkoly . Pokud to chcete potvrdit, podívejte se do okna Paralelní zásobníky . Ujistěte se, že si prohlížíte úkoly. Úkoly 11 a 12 můžete vyhledat tak, že v okně Paralelní zásobníky vyhledáte popisy.

Task view in Parallel Stacks window

Nový úkol, úkol 5, je nyní spuštěný a úkol 4 teď čeká. Důvod můžete zjistit tak, že v okně Stav najedete myší na čekající úkol. Ve sloupci Nadřazený si všimněte, že úkol 4 je nadřazený úkolu 5.

Pokud chcete lépe vizualizovat vztah nadřazený-podřízený, klikněte pravým tlačítkem myši na řádek záhlaví sloupce a vyberte nadřazené podřízené zobrazení. Měl by se zobrazit následující obrázek.

Parent-child view in Tasks window

Všimněte si, že úloha 4 a úkol 5 běží ve stejném vlákně (pokud je skrytý, zobrazte sloupec Přiřazení vlákna). Tyto informace se nezobrazují v okně Vlákna . Tady je další výhoda okna Úkoly . Pokud to chcete potvrdit, podívejte se do okna Paralelní zásobníky . Ujistěte se, že si prohlížíte úkoly. Úkoly 4 a 5 vyhledejte poklikáním v okně Úkoly . Když to uděláte, aktualizuje se modré zvýraznění v okně Paralelní zásobníky . Úkoly 4 a 5 můžete vyhledat také tak, že v okně Paralelní zásobníky vyhledáte popisy.

Task view in Parallel Stacks window

V okně Paralelní zásobníky klikněte pravým tlačítkem na S.P a pak vyberte Přejít na vlákno. Okno se přepne do zobrazení vláken a odpovídající rámec je v zobrazení. Oba úlohy můžete zobrazit ve stejném vlákně.

Highlighted thread in threads view

Toto je další výhodou zobrazení úloh v okně Paralelní zásobníky v porovnání s oknem Vlákna .

Pokračovat v provádění až do čtvrté zarážky

Pokud chcete pokračovat v provádění, dokud se nenarazí třetí zarážka, vyberte v nabídce Ladění možnost Pokračovat. Vyberte záhlaví sloupce ID pro řazení podle ID. Měl by se zobrazit následující obrázek.

Screenshot of Four task states in Parallel Stacks window.

Úkol 10 a úkol 11 teď čekají na sebe a jsou blokované. Nyní je naplánováno také několik nových úkolů. Naplánované úkoly jsou úkoly, které byly spuštěny v kódu, ale ještě nebyly spuštěny. Sloupce Umístění a Přiřazení vláken proto zobrazují výchozí zprávy nebo jsou prázdné.

Four task states in Parallel Stacks window

Vzhledem k tomu, že úkol 5 byl dokončen, už se nezobrazuje. Pokud to není případ ve vašem počítači a zablokování se nezobrazí, krokujte jedním stisknutím klávesy F11.

Úkol 3 a úkol 4 teď čekají na sebe a jsou blokované. K dispozici je také 5 nových úkolů, které jsou podřízené úkolu 2 a nyní jsou naplánované. Naplánované úkoly jsou úkoly, které byly spuštěny v kódu, ale ještě nebyly spuštěny. Sloupce Umístění a Přiřazení vláken jsou proto prázdné.

Znovu zobrazte okno Paralelní zásobníky. Záhlaví každého pole obsahuje popis, který zobrazuje ID a názvy vláken. Přepněte do zobrazení úkolů v okně Paralelní zásobníky . Najeďte myší na záhlaví, abyste viděli ID a název úkolu a stav úkolu, jak je znázorněno na následujícím obrázku.

Header tooltip in Parallel Stacks window

Úkoly můžete seskupit podle sloupce. V okně Úkoly klikněte pravým tlačítkem myši na záhlaví sloupce Stav a pak vyberte Seskupovat podle stavu. Následující obrázek znázorňuje okno Úkoly seskupené podle stavu.

Screenshot of Grouped tasks in Tasks window.

Grouped tasks in Tasks window

Můžete také seskupit podle libovolného jiného sloupce. Seskupením úkolů se můžete zaměřit na podmnožinu úkolů. Každá sbalitelná skupina má počet položek, které jsou seskupené dohromady.

Poslední funkcí okna Úkoly , které chcete prozkoumat, je místní nabídka, která se zobrazí po kliknutí pravým tlačítkem myši na úkol.

Místní nabídka zobrazuje různé příkazy v závislosti na stavu úkolu. Příkazy můžou zahrnovat kopírovat, vybrat vše, šestnáctkové zobrazení, přepnout na úlohu, ukotvit přiřazené vlákno, ukotvit všechna vlákna, ale to a příznak Přiřazené vlákno Thaw.

Můžete ukotvit základní vlákno úlohy nebo úkolů nebo můžete ukotvit všechna vlákna kromě přiřazeného vlákna. Ukotvené vlákno je znázorněno v okně Úkoly , protože je v okně Vlákna , modrou ikonou pozastavení .

Shrnutí

Tento názorný postup ukázal okna ladicího programu paralelních úloh a paralelních zásobníků . Tato okna použijte v reálných projektech, které používají vícevláknový kód. Můžete prozkoumat paralelní kód napsaný v jazyce C++, C# nebo Visual Basic.