Wskazówki: debugowanie aplikacji równoległych
W tym instruktażu przedstawiono sposób użycia Zadania równolegle i Równolegle stosy systemu windows do debugować aplikacji równolegle.Okna te ułatwić zrozumienie i sprawdzić działanie runtime kod, który używa Biblioteka zadań równoległych (TPL) lub Współbieżność środowiska wykonawczego.Ten instruktaż zawiera przykładowy kod, który ma wbudowane punkty przerwania.Po podziały wierszy kodu, instruktaż ilustruje sposób użycia Zadania równolegle i Równolegle stosy systemu windows do zbadania jej.
W tym instruktażu uczy tych zadań:
Jak wyświetlić stosy wywołań wszystkich wątków w jednym widoku.
Jak wyświetlić listę System.Threading.Tasks.Task wystąpień, które są tworzone w aplikacji.
Jak wyświetlić stosy wywołań rzeczywiste zadań zamiast wątków.
Jak przechodzenie do kodu z Zadania równolegle i Równolegle stosy systemu windows.
Jak windows radzenia sobie ze skalą poprzez grupowanie, powiększanie i inne funkcje pokrewne.
Wymagania wstępne
W tym instruktażu zakłada się, że Just Mój kod jest włączone.Na Narzędzia menu, kliknij Opcje, rozwiń węzeł Debugowanie węzła, zaznacz Ogólne, a następnie wybierz włączyć tylko Mój kod (tylko zarządzane). Jeśli ta cechanie jest ustawiona, można nadal używać w tym instruktażu, ale wyniki mogą różnić się od ilustracji.
C# próbki
Użycie języka C# próbki, w tym instruktażu założono również, że kod zewnętrzny jest ukryty.Aby przełączyć czy kod zewnętrzny jest wyświetlany, kliknij prawym przyciskiem myszy Nazwa tabeli nagłówek Stos okno, a następnie wybierz lub wyczyść Pokaż kod zewnętrzny. Jeśli ta cechanie jest ustawiona, można nadal używać w tym instruktażu, ale wyniki mogą różnić się od ilustracji.
Próbki C++
Jeśli używasz próbki C++, można zignorować odniesienia do zewnętrznego kodu w tym temacie.Kod zewnętrzny dotyczy tylko próbkę C#.
Ilustracje
Ilustracje, w tym temacie są rejestrowane na komputerze czterordzeniowe z próbki C#.Chociaż można użyć innych konfiguracji do przeprowadzenia tego instruktażu, ilustracji może różnić się od wyświetlanego na komputerze.
Tworzenie projektu próbki
Kod przykładowy, w tym instruktażu jest dla aplikacji, która nie wykonuje żadnej operacji.cel jest po prostu zrozumienie sposobu korzystania z systemu windows narzędzie do debugować aplikacji równolegle.
Aby utworzyć przykładowy projekt
W Visual Studiona pliku menu, wskaż Nowy , a następnie kliknij przycisk Projekt.
W Zainstalowane szablonyokienko, zaznacz albo Visual C#, Visual Basiclub Visual C++. Dla języków zarządzanych, zapewnić, że Program .NET Framework 4 jest wyświetlany w polu ramy.
Wybierz Console Application , a następnie kliknij przycisk OK.Pozostają w konfiguracjadebugowania, co jest ustawieniem domyślnym.
Otwórz plik kodu .cpp, .cs lub .vb w projekt.Usunąć jego zawartość, aby utworzyć plik kod pusty.
Wklej następujący kod dla wybranego języka do pliku kod pusty.
Imports System
Imports System.Threading
Imports System.Threading.Tasks
Imports System.Diagnostics
Module S
Sub Main()
pcount = Environment.ProcessorCount
Console.WriteLine("Proc count = " + pcount.ToString())
ThreadPool.SetMinThreads(4, -1)
ThreadPool.SetMaxThreads(4, -1)
t1 = New Task(AddressOf A, 1)
t2 = New Task(AddressOf A, 2)
t3 = New Task(AddressOf A, 3)
t4 = New Task(AddressOf 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()
End Sub
Sub A(ByVal o As Object)
B(o)
End Sub
Sub B(ByVal o As Object)
C(o)
End Sub
Sub C(ByVal o As Object)
Dim temp As Integer = o
Interlocked.Increment(aa)
While (aa < 4)
End While
If (temp = 1) Then
' BP1 - all tasks in C
Debugger.Break()
waitFor1 = False
Else
While (waitFor1)
End While
End If
Select Case temp
Case 1
D(o)
Case 2
F(o)
Case 3, 4
I(o)
Case Else
Debug.Assert(False, "fool")
End Select
End Sub
Sub D(ByVal o As Object)
E(o)
End Sub
Sub E(ByVal o As Object)
' break here at the same time as H and K
While (bb < 2)
End While
'BP2 - 1 in E, 2 in H, 3 in J, 4 in K
Debugger.Break()
Interlocked.Increment(bb)
'after
L(o)
End Sub
Sub F(ByVal o As Object)
G(o)
End Sub
Sub G(ByVal o As Object)
H(o)
End Sub
Sub H(ByVal o As Object)
' break here at the same time as E and K
Interlocked.Increment(bb)
Monitor.Enter(mylock)
While (bb < 3)
End While
Monitor.Exit(mylock)
'after
L(o)
End Sub
Sub I(ByVal o As Object)
J(o)
End Sub
Sub J(ByVal o As Object)
Dim temp2 As Integer = o
Select Case temp2
Case 3
t4.Wait()
Case 4
K(o)
Case Else
Debug.Assert(False, "fool2")
End Select
End Sub
Sub K(ByVal o As Object)
' break here at the same time as E and H
Interlocked.Increment(bb)
Monitor.Enter(mylock)
While (bb < 3)
End While
Monitor.Exit(mylock)
'after
L(o)
End Sub
Sub L(ByVal oo As Object)
Dim temp3 As Integer = oo
Select Case temp3
Case 1
M(oo)
Case 2
N(oo)
Case 4
O(oo)
Case Else
Debug.Assert(False, "fool3")
End Select
End Sub
Sub M(ByVal o As Object)
' breaks here at the same time as N and Q
Interlocked.Increment(cc)
While (cc < 3)
End While
'BP3 - 1 in M, 2 in N, 3 still in J, 4 in O, 5 in Q
Debugger.Break()
Interlocked.Increment(cc)
While (True)
Thread.Sleep(500) ' for ever
End While
End Sub
Sub N(ByVal o As Object)
' breaks here at the same time as M and Q
Interlocked.Increment(cc)
While (cc < 4)
End While
R(o)
End Sub
Sub O(ByVal o As Object)
Dim t5 As Task = Task.Factory.StartNew(AddressOf P, TaskCreationOptions.AttachedToParent)
t5.Wait()
R(o)
End Sub
Sub P()
Console.WriteLine("t5 runs " + Task.CurrentId.ToString())
Q()
End Sub
Sub Q()
' breaks here at the same time as N and M
Interlocked.Increment(cc)
While (cc < 4)
End While
' task 5 dies here freeing task 4 (its parent)
Console.WriteLine("t5 dies " + Task.CurrentId.ToString())
waitFor5 = False
End Sub
Sub R(ByVal o As Object)
If (o = 2) Then
' wait for task5 to die
While waitFor5
End While
'//spin up all procs
Dim i As Integer
For i = 0 To pcount - 4 - 1
Dim t As Task = Task.Factory.StartNew(Sub()
While True
End While
End Sub)
Console.WriteLine("Started task " + t.Id.ToString())
Next
Task.Factory.StartNew(AddressOf T, i + 1 + 5, TaskCreationOptions.AttachedToParent) ' //scheduled
Task.Factory.StartNew(AddressOf T, i + 2 + 5, TaskCreationOptions.AttachedToParent) ' //scheduled
Task.Factory.StartNew(AddressOf T, i + 3 + 5, TaskCreationOptions.AttachedToParent) ' //scheduled
Task.Factory.StartNew(AddressOf T, i + 4 + 5, TaskCreationOptions.AttachedToParent) ' //scheduled
Task.Factory.StartNew(AddressOf 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(o = 4)
t3.Wait()
End If
End Sub
Sub T(ByVal o As Object)
Console.WriteLine("Scheduled run " + Task.CurrentId.ToString())
End Sub
Private t1, t2, t3, t4 As Task
Private aa As Integer = 0
Private bb As Integer = 0
Private cc As Integer = 0
Private waitFor1 As Boolean = True
Private waitFor5 As Boolean = True
Private pcount As Integer
Private mylock As New S2()
End Module
Public Class S2
End Class
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();
}
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <ppl.h>
#include <agents.h>
#include <stdio.h>
#include <concrtrm.h>
#include <vector>
CRITICAL_SECTION cs;
using namespace ::std;
using namespace ::std::tr1;
using namespace ::Concurrency;
task_group task4;
task_group task3;
task_group task2;
volatile long aa = 0;
volatile long bb = 0;
volatile long cc = 0;
static bool waitFor1 = true;
static bool waitFor5 = true;
#pragma optimize("", off)
void Spin()
{
for(int i=0;i<50*50000;++i);
}
#pragma optimize("",on)
template<class Func>
class RunFunc
{
Func& m_Func;
int m_o;
public:
RunFunc(Func func,int o):m_Func(func),m_o(o){
};
void operator()()const{
m_Func(m_o);
};
};
void T(int o)
{
cout << "Scheduled run \n";
};
void R(int o)
{
if (o == 2)
{
while (waitFor5) { ;}
Spin();
//use up all processors but 4 by scheduling 4 non-terminating tasks.
int numProcsToBurn = GetProcessorCount() - 4;
int i;
vector<call<int>*> tasks;
for (i = 0; i < numProcsToBurn; i++)
{
tasks.push_back(new call<int>([](int i){while(true)Spin();}));
asend(tasks[i],1);
cout << "Started task \n";
}
task_handle<RunFunc<decltype(T)>> t6(RunFunc<decltype(T)>(T,i + 1 + 5));
task_handle<RunFunc<decltype(T)>> t7(RunFunc<decltype(T)>(T,i + 2 + 5));
task_handle<RunFunc<decltype(T)>> t8(RunFunc<decltype(T)>(T,i + 3 + 5));
task_handle<RunFunc<decltype(T)>> t9(RunFunc<decltype(T)>(T,i + 4 + 5));
task_handle<RunFunc<decltype(T)>> t10(RunFunc<decltype(T)>(T,i + 5 + 5));
task2.run(t6);
task2.run(t7);
task2.run(t8);
task2.run(t9);
task2.run(t10);
//BP4 - 1 in M, 2 in R, 3 in J, 4 in R, 5 died
DebugBreak();
}
else
{
if (o!=4)
throw;
task3.wait();
}
};
void Q()
{
// breaks here at the same time as N and M
InterlockedIncrement(& cc);
while (cc < 4)
{
;
}
// task 5 dies here freeing task 4 (its parent)
cout << "t5 dies\n";
waitFor5 = false;
};
void P()
{
cout << "t5 runs\n";
Q();
};
void O(int o)
{
task_group t5;
t5.run(&P);
t5.wait();
R(o);
};
void N(int o)
{
// breaks here at the same time as M and Q
InterlockedIncrement(&cc);
while (cc < 4)
{
;
}
R(o);
};
void M(int o)
{
// breaks here at the same time as N and Q
InterlockedIncrement(&cc);
while (cc < 3)
{
;
}
//BP3 - 1 in M, 2 in N, 3 still in J, 4 in O, 5 in Q
DebugBreak();
InterlockedIncrement(&cc);
while (true)
Sleep(500); // for ever
};
void L(int oo)
{
int temp3 = oo;
switch (temp3)
{
case 1:
M(oo);
break;
case 2:
N(oo);
break;
case 4:
O(oo);
break;
default:
throw; //fool3
break;
}
}
void K(int o)
{
// break here at the same time as E and H
InterlockedIncrement(&bb);
EnterCriticalSection(&cs);
while (bb < 3)
{
;
}
LeaveCriticalSection(&cs);
Spin();
//after
L(o);
}
void J(int o)
{
int temp2 = o;
switch (temp2)
{
case 3:
task4.wait();
break;
case 4:
K(o);
break;
default:
throw; //fool2
break;
}
}
static void I(int o)
{
J(o);
}
static void H(int o)
{
// break here at the same time as E and K
InterlockedIncrement(&bb);
EnterCriticalSection(&cs);
while (bb < 3)
{
;
}
LeaveCriticalSection(&cs);
Spin();
//after
L(o);
}
static void G(int o)
{
H(o);
}
static void F(int o)
{
G(o);
}
static void E(int 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
Spin(); // for native case only
DebugBreak();
InterlockedIncrement(&bb);
//after
L(o);
}
static void D(int o)
{
E(o);
}
static void C(int o)
{
int temp = o;
InterlockedIncrement(&aa);
while (aa < 4)
{
;
}
if (temp == 1)
{
// BP1 - all tasks in C
DebugBreak();
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:
throw; //fool
break;
}
}
static void B(int o)
{
C(o);
}
void A(int o)
{
B(o);
}
int main()
{
InitializeCriticalSection(&cs);
task_group tasks;
task_handle<RunFunc<decltype(A)>> t1(RunFunc<decltype(A)>(A,1));
tasks.run(t1);
task_handle<RunFunc<decltype(A)>> t2(RunFunc<decltype(A)>(A,2));
task2.run(t2);
task_handle<RunFunc<decltype(A)>> t3(RunFunc<decltype(A)>(A,3));
task3.run(t3);
task_handle<RunFunc<decltype(A)>> t4(RunFunc<decltype(A)>(A,4));
task4.run(t4);
getchar();
return 1;
}
Na pliku menu, kliknij przycisk Zapisz wszystkie.
Na budować menu, kliknij przycisk Roztwór odbudować.
Są cztery wywołania Debugger.Break (DebugBreak w próbce C++) w związku z tym, nie trzeba wstawiać punkty przerwania; tylko z uruchomioną aplikacją spowoduje zerwanie w debugerze maksymalnie cztery razy.
Za pomocą okna stosy równoległego: Widok wątków
Na debugowania menu, kliknij przycisk Start Debugging. Poczekaj, aż pierwszy punkt przerwania można trafić.
Aby wyświetlić pojedynczy wątek stos wywołań
Na debugowania menu, wskaż Windows , a następnie kliknij przycisk wątków. Zadokuj wątkówokno u dołu Visual Studio.
Na debugowania menu, wskaż Windows , a następnie kliknij przycisk Stos. Zadokuj Stosokno u dołu Visual Studio.
Kliknij dwukrotnie ikonę wątek w wątkówokno , aby bieżący. Bieżące wątki posiadają żółta strzałka.Po zmianie bieżącego wątekjej stos wywołań jest wyświetlany w Stosokno.
Do zbadania równoległych stosy okno
Na debugowania menu, wskaż Windows , a następnie kliknij przycisk Równolegle stosy. Upewnij się, że wątków jest zaznaczona w polu znajdującym się w lewym górnym rogu.
Za pomocą Równolegle stosy okno, można wyświetlić wiele stosy wywołań, w tym samym czasie w jednym widoku.Na poniższej ilustracji pokazano Równolegle stosy okno powyżej Stosokno.
stos wywołań wątek głównego pojawi się w jednym polu i stosy wywołań dla cztery wątki są zgrupowane w innym polu.Cztery wątki są grupowane razem, ponieważ ich ramek stosu używają tej samej kontekstów metoda ; oznacza to, że są one w tej samej metody: A, B, i C.Widok wątek identyfikatory i nazwy wątków, które współużytkują ten sam pole, przesuń kursor nad nagłówek (4 wątki).Bieżący wątek jest wyświetlana w pogrubienie, jak pokazano na poniższej ilustracji.
Żółta strzałka wskazuje aktywny stosu ramka bieżącego wątek.Aby uzyskać więcej informacji, przemieść nad nim wskaźnik
Można ustawić ilość szczegółów, aby pokazać ramek stosu (Nazwy modułu, Typy parametrów, Nazwy parametru, Wartości parametrów, Numery linii i Bajt jest przeciwstawna) przez kliknięcie prawym przyciskiem myszy, w Stosokno.
Niebieski podświetlenia wokół pola wskazuje, że bieżący wątek jest częścią tego pola.Bieżący wątek jest również wskazywane przez pogrubienie stosu ramka w etykietce narzędzia.Jeśli klikniesz dwukrotnie głównego wątek w wątki okno, można zaobserwować, że niebieskie podświetlenie w Stosy równolegleokno porusza się odpowiednio.
Aby wznowić wykonywanie aż do drugiego punkt przerwania
Wznowienie wykonywania, dopóki drugi punkt przerwania jest hit, z debugowania menu, kliknij przycisk Kontynuuj. Na następującej ilustracji pokazano wątek drzewo na drugi punkt przerwania.
Na pierwszy punkt przerwaniawszystkie cztery wątki wzrósł od S.A do S.B do metody S.C.Że informacje są nadal widoczne w Równolegle stosyokno, ale cztery wątki postępują dalszych. Jeden z nich nadal S.D, a następnie S.E.Inny nadal S.F, S.G i S.H.Dwa inne nadal S.I i S.J oraz z nim jedno z nich udał się do S.K i kontynuowane drugiej do innych niż - kod zewnętrznyużytkownik .
Można na przykład wskaźnik nad pole nagłówek, 1 wątek lub 2 wątki, aby zobaczyć wątek identyfikatory wątków.Można Aktywuj ramek stosu, aby zobaczyć identyfikatory wątek , plus inne szczegóły ramka .Wyróżnij niebieskie wskazuje bieżący wątek i żółta strzałka wskazuje aktywny stosu ramka bieżącego wątek.
Ikona szmatką wątków (nakładających się niebieski i czerwony waved linie) wskazują ramek stosu aktywnych wątków, inne niż bieżące.W Stosokno, kliknij dwukrotnie S.B, aby przełączyć ramek. Równolegle stosyokno wskazuje bieżącą stosu ramka z bieżącego wątek za pomocą ikony zieloną strzałkę zakrzywioną.
W wątków oknoprzełączyć się pomiędzy wątkami i że widoku w Równolegle stosyokno jest aktualizowany.
Można przełączyć do innego wąteklub do innej ramka inny wątekprzy użyciumenu skrótw Równolegle stosyokno. Na przykład, kliknij prawym przyciskiem myszy S.J, wskaż polecenie Przełącznika do ramki, a następnie kliknij odpowiednie polecenie.
Kliknij prawym przyciskiem myszy S.C, a następnie wskaż polecenie Przełącznika do ramki.Jedno z poleceń ma znacznik wyboru wskazuje stosu ramka z bieżącego wątek.Przełącz się do tej ramka w tym samym wątek (tylko zielona strzałka spowoduje przeniesienie) lub przełączyć się do innego wątek (niebieski zostanie również zaznaczony).Na następującej ilustracji pokazano podmenu.
Gdy metodakontekst jest skojarzony z stos tylko jedną ramka, pole nagłówek Wyświetla 1 wątku i nastąpi przełączenie do niego przez dwukrotne kliknięcie. Jeśli klikniesz dwukrotnie metoda kontekst , który ma więcej niż 1 ramka skojarzony z nim, następnie w menu automatycznie pojawia się.Jako wskaźnik nad kontekstów metoda , należy zauważyć, czarny trójkąt po prawej stronie.Również kliknięcie tym trójkąt Wyświetlamenu skrót.
Dla dużych aplikacji, które mają wiele wątków chcesz skupić się na ich podzbiór wątków.Równolegle stosymożna wyświetlić wokno stosy wywołań tylko dla wątków oznaczone flagami. Na pasku narzędzi kliknij przycisk Pokaż tylko oflagowane przycisk Dalej, aby pole listy.
W następnej wątków okno oflagować wątki jeden po drugim, aby zobaczyć, jak ich stosy wywołań pojawiają się w Równolegle stosyokno. oflagować wątków użyjmenu skrótlub pierwszą komórkę wątek. Kliknij przycisk Pokaż tylko oflagowane przycisk paska narzędzi ponownie, aby wyświetlić wszystkie wątki.
Aby wznowić wykonywanie aż do trzeciego punkt przerwania
Wznowienie wykonywania, dopóki trzeci punkt przerwania jest hit, z debugowania menu, kliknij przycisk Kontynuuj.
Gdy wiele wątków są w tej samej metoda , ale metoda nie był na początku stos wywołań, metoda pojawia się w różnych polach.Przykładem na bieżący punkt przerwania jest S.L, który ma trzy wątki i pojawia się w trzech polach.Kliknij dwukrotnie S.L.
Należy zauważyć, że S.L jest pogrubiony w innych polach, dzięki czemu można zobaczyć, gdzie indziej pojawia się.Jeśli chcesz zobaczyć które ramki wywołanie do S.L i które ramki go wywołania, kliknij przycisk Przełącz widok metoda przycisku na pasku narzędzi.Na następującej ilustracji pokazano widok metoda Równolegle stosy okno.
Należy zauważyć, jak diagram przestawiany na wybranej metoda i on umieszczony w jego własne pole w środku widoku.Zapobieganie i wywoływania są wyświetlane na górze i na dole.Kliknij przycisk Przełącz widok metoda przycisk ponownie, aby opuścić ten tryb.
Wmenu skrótz Równolegle stosyokno zawiera również następujące inne elementy.
Wyświetlanie szesnastkowych przełącza numery w etykietkach narzędzi między liczba dziesiętna i szesnastkowo.
Symbol informacji obciążenia i Ustawienia Symbol otwarty odpowiednich oknach dialogowych.
Przejdź do kodu źródłowego i Go do demontażu nawigowanie w edytor wybranej metoda.
Pokaż kod zewnętrzny Wyświetla wszystkie ramki, nawet jeśli nie są w kodzie użytkownik .Spróbuj wyświetlić diagram, rozwiń, aby pomieścić dodatkowe ramki, (które mogą być nieaktywne, ponieważ nie masz symbole dla nich).
Gdy masz dużych diagramów i kroku do następnego punkt przerwania, może być w celu automatycznego przewijania do stosu active ramka bieżącego wątek; oznacza to, że wątek , który pierwszy hit punkt przerwania .W Równolegle stosy okno, upewnij się, że Autoprzewijanie do bieżącej klatki stosu znajduje się na przycisku na pasku narzędzi.
Zanim będziesz kontynuować, w Równolegle stosyokno, przewijania wszystkich sposób, w lewo i w dół do końca.
Aby wznowić wykonywanie aż do czwartego punkt przerwania
Wznowienie wykonywania, dopóki czwarty punkt przerwania jest hit, z debugowania menu, kliknij przycisk Kontynuuj.
Zawiadomienie jak autoscrolled widok na miejscu.Przełączanie wątków w wątków stosuokno lub przełącznik ramki w Stosokno i ogłoszenia jak widok zawsze autoscrolls do poprawnej ramka. Wyłącz Autoprzewijanie do bieżącej klatki narzędzie opcji i umożliwia wyświetlanie różnicy.
Widok z lotu ptaka również pomaga w dużych diagramów w Równolegle stosyokno. Można zobaczyć Widok z lotu ptaka przez kliknięcie przycisku między paskami przewijania w prawym dolnym rogu okno, jak pokazano na poniższej ilustracji.
Można przenieść prostokąt, szybkie przesuwanie na diagramie.
Przenoszenie diagramu w dowolnym kierunku w inny sposób jest kliknij pusty obszar na diagramie i przeciągnij go w wybrane miejsce.
powiększyć z diagramu naciśnij i przytrzymaj klawisz CTRL podczas przenoszenia kółko mysz .Alternatywnie kliknij przycisk powiększenia na pasku narzędzi, a następnie użyj narzędzia Lupka.
Można również wyświetlić stosy w kierunku góra dół, zamiast w dół góra, klikając Narzędzia menu, klikając polecenie Opcje, a następnie zaznacz lub wyczyść opcję w obszarze Debugowanie węzła.
Przed rozpoczęciem pracy z debugowania menu, kliknij przycisk Stop Debugging do realizacji celu.
Przy użyciu okna zadania równolegle i widoku zadania równolegle stosy okno
Zaleca się, aby zakończyć procedury wcześniej, przed kontynuowaniem.
Hit jest ponowne uruchomienie aplikacji aż do pierwszego punkt przerwania
Na debugowania menu, kliknij przycisk Start Debugging i czeka na pierwszy punkt przerwania można trafić.
Na debugowania menu, wskaż Windows , a następnie kliknij przycisk wątków. Zadokuj wątkówokno u dołu Visual Studio.
Na debugowania menu, wskaż Windows i kliknij przycisk Stos. Zadokuj Stosokno u dołu Visual Studio.
Kliknij dwukrotnie ikonę wątek w wątkówokno czyni bieżącego. Bieżące wątki posiadają żółta strzałka.Po zmianie bieżącego wątekinne okna są aktualizowane.Następnie będziemy sprawdzać zadań.
Na debugowania menu, wskaż Windows , a następnie kliknij przycisk Zadania równolegle. Na poniższej ilustracji pokazano Zadania równolegleokno.
Dla każdego działającego zadania można odczytać Identyfikatora, który jest zwracany przez właściwośćo tej samej nazwie, identyfikator i nazwę wątek , który jest uruchamiany, jego lokalizację (najechanie ten wyświetla etykietka, która ma cały stos wywołań).Ponadto, w obszarze zadania kolumny, można wyświetlić metoda przekazano zadania; innymi słowy punkt początkowy.
Można sortować dowolnej kolumny.Zawiadomienie sortowania symbol , który wskazuje sortowanie kolumn i kierunek.Można również zmienić kolejność kolumn, przeciągając je w lewo lub w prawo.
Żółta strzałka wskazuje bieżące zadanie.Zadania można przełączać, klikając dwukrotnie ikonę zadania lub za pomocąmenu skrót. Podczas przełączania zadań podstawowej wątek staje się bieżącym i inne okna są aktualizowane.
Gdy ręcznie przełączać się z jednego zadania do innego, żółta strzałka przemieszcza się białej strzałki nadal pokazuje zadania, który spowodował debugera przerwać.
Aby wznowić wykonywanie aż do drugiego punkt przerwania
Wznowienie wykonywania, dopóki drugi punkt przerwania jest hit, z debugowania menu, kliknij przycisk Kontynuuj.
Wcześniej stanu kolumny wykazało, jak uruchamianie wszystkich zadań, ale teraz dwóch zadań oczekujących.Zadania mogą być blokowane dla wielu różnych powodów.W stanu kolumny, aktywowania za pośrednictwem zadań oczekujących, aby dowiedzieć się, dlaczego jest ono blokowane.Na przykład na poniższej ilustracji, zadanie 3 jest oczekiwanie na zadanie 4.
Zadanie 4, z kolei jest oczekiwanie na monitorze, posiadane przez wątek przydzielony do zadania 2.
Można zadanie oflagować klikając w pierwszej kolumnie oflagować Zadania równolegleokno.
Flagi monitujące – można użyć do śledzenia zadań między różne punkty przerwania w tej samej sesji debugowanie lub filtr zadań, których stosy wywołań są wyświetlane w Równolegle stosyokno.
Kiedy używane Równolegle stosyokno wcześniej, przeglądać wątki aplikacji. Widok Równolegle stosyokno ponownie, ale tym razem wyświetlanie zadań aplikacji. To zrobić, zaznaczając zadania w polu w lewym górnym rogu.Następująca ilustracja pokazuje widok zadań.
Wątki, które nie są aktualnie wykonywanych zadań nie są wyświetlane w widoku zadania z Równolegle stosyokno. Ponadto w przypadku wątków, że wykonać zadania niektórych ramek stosu, które nie są odpowiednie do zadań są filtrowane z góry i u dołu stosu.
Widok Zadania równolegleponownieokno . Kliknij prawym przyciskiem myszy dowolny nagłówek kolumny aby wyświetlićmenu skrótdla kolumny.
Aby dodać lub usunąć kolumny, można użyćmenu skrót. Na przykład kolumna domena aplikacji nie została wybrana; w związku z tym nie jest wyświetlany na liście.Kliknij przycisk nadrzędnej.Nadrzędnej kolumna jest wyświetlana bez wartości dla każdego z czterech zadań.
Aby wznowić wykonywanie aż do trzeciego punkt przerwania
Wznowienie wykonywania, dopóki trzeci punkt przerwania jest hit, z debugowania menu, kliknij przycisk Kontynuuj.
Nowe zadanie zadania 5, obecnie jest uruchomiony i obecnie oczekuje zadanie 4.Można zobaczyć, dlaczego poprzez najechanie wskaźnikiem zadań oczekujących w stanuokno. W nadrzędnej kolumny, zawiadomienie to zadanie 4 jest nadrzędny zadanie 5.
Aby lepiej uświadomić sobieelement podrzędnynadrzędny -relacja, kliknij prawym przyciskiem myszy nadrzędnej kolumna, nagłówek , a następnie kliknij przycisk Widok podrzędny nadrzędnej. Następująca ilustracja powinny być widoczne.
Należy zauważyć, że zadanie 4 i 5 zadania są uruchomione na tym samym wątek.Te informacje nie są wyświetlane w wątkówokno; zobaczenie go tutaj jest inną korzyścią płynącą z Zadania równolegleokno. Można to potwierdzić, wyświetlić Równolegle stosyokno. Upewnij się, że oglądasz zadania.Znajdź zadania, 4 i 5 przez dwukrotne kliknięcie pliku w Zadania równolegleokno. Powoduje to podświetlenie niebieski Równolegle stosyokno jest aktualizowany. Możesz również znaleźć zadania, 4 i 5, skanując etykietki narzędzi na Równolegle stosyokno.
W Równolegle stosy okno, kliknij prawym przyciskiem myszy S.P, a następnie kliknij przycisk Go do wątku. W okno przełącza na widok wątków i odpowiadające im ramka jest w widoku.W tym samym wątek, można wyświetlić oba zadania.
Jest to korzyść innego widoku zadań, w Równolegle stosy okno, w porównaniu do wątkówokno.
Aby wznowić wykonywanie aż do czwartego punkt przerwania
Wznowienie wykonywania, dopóki trzeci punkt przerwania jest hit, z debugowania menu, kliknij przycisk Kontynuuj. Kliknij przycisk ID nagłówek kolumny, aby posortować według identyfikatora.Następująca ilustracja powinny być widoczne.
Ponieważ zadanie 5 zostało ukończone, jest już wyświetlany.Jeśli nie jest to przypadek na komputerze i zakleszczenie nie jest widoczne, krok jeden raz, naciskając klawisz F11.
Zadanie 3 i 4 zadań teraz trwa oczekiwanie na siebie i są zakleszczone.Istnieją również 5 nowych zadań, które są dzieci 2 zadania i są obecnie zaplanowane.Zaplanowane zadania są zadania, które zostały rozpoczęte w kodzie, ale nie zostały jeszcze uruchomiony.W związku z tym ich lokalizację i Przydziału wątku kolumny są puste.
Widok Równolegle stosyponownieokno . nagłówek każde pole ma etykietce narzędzia, która zawiera identyfikatory wątek i nazwy.Przełącz się do widoku zadań w Równolegle stosyokno. Aktywuj nagłówek , aby zobaczyć identyfikator zadania oraz nazwę i stan zadania, jak pokazano na poniższej ilustracji.
Możesz grupa zadań według kolumny.W Zadania równolegle okno, kliknij prawym przyciskiem myszy stanu kolumna, nagłówek , a następnie kliknij przycisk grupy według stanu. Na poniższej ilustracji pokazano Zadania równolegleokno pogrupowane według stan.
Można również grupa przez inną kolumnę.Grupowanie zadań możesz skupić podzbiór zadań.Każda zwijany grupa ma liczba elementów, które są zgrupowane razem.Można również szybko oflagować wszystkich elementów w grupa klikając Flaga przycisk po prawej stronie Zwiń przycisku.
Ostatnia cecha z Zadania równolegleokno , aby zbadać jestmenu skrót, wyświetlanego po kliknięciu zadania prawym przyciskiem myszy.
skrótmenu wyświetla różne polecenia, w zależności od stan zadania. Polecenia mogą zawierać kopię, Zaznacz wszystko, Wyświetlanie szesnastkowych, przełącznik do zadania, Zamrozić przypisane wątku, Zablokować wszystkie wątki, ale ten, i Rozmrażanie przypisane wątku, i Flaga.
Można blokować podstawowej wątek lub zadania, lub można blokować wszystkie wątki, z wyjątkiem przypisany jeden.Mrożone wątek jest reprezentowana w Zadania równolegle okno jak to jest w wątków okno, Blue wstrzymać ikona.
Podsumowanie
Wykazane w tym instruktażu Zadania równolegle i Równolegle stosy debuger systemu windows.Użyj tych okien na rzeczywistych projektów korzystających wielowątkowe kodu.Można sprawdzić równoległych kod napisany w C++, C# lub Visual Basic.
Zobacz też
Zadania
Wskazówki: debugowanie aplikacji równoległych
Koncepcje
Współbieżność środowiska wykonawczego
Korzystanie z okna stosów równoległych