C#中一些你可能沒(méi)用過(guò)的調(diào)試窗口的方法
首先說(shuō)明:如果沒(méi)有進(jìn)入調(diào)試模式的話,默認(rèn)的調(diào)試窗口如下:
開(kāi)始前的準(zhǔn)備:
新建控制臺(tái)程序DebugWindowDemo:
修改Program.cs 的代碼為:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
class S
{
public 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();
}
按F5,開(kāi)始運(yùn)行:
由于Debugger.Break();
所以當(dāng)執(zhí)行到這里的時(shí)候,Debugger會(huì)中斷。
這個(gè)時(shí)候再看看調(diào)試窗口會(huì)發(fā)現(xiàn)多了幾個(gè)窗口:
點(diǎn)擊調(diào)試->窗口->并行任務(wù),界面如下:
按下F5,繼續(xù)運(yùn)行:
雙擊查看相應(yīng)等待的任務(wù),就可以知道這個(gè)工作線程為什么等待了。
例如:
繼續(xù)按F5,運(yùn)行,你應(yīng)該會(huì)看到:
總之關(guān)于當(dāng)前運(yùn)行的并行任務(wù)你都可以看的到。
關(guān)閉程序,重新F5,進(jìn)入調(diào)試模式
選擇調(diào)試->窗口->并行堆棧
可以看到:
其中藍(lán)線代表當(dāng)前正在執(zhí)行的線程。
如果右鍵點(diǎn)擊方法視圖的S.C ,可以看到右鍵菜單如下:
點(diǎn)擊切換方法視圖
可以看到:
關(guān)閉程序,重新F5,進(jìn)入調(diào)試模式
點(diǎn)擊調(diào)試->窗口->線程:
可以看到:
當(dāng)前控制臺(tái)的所有線程都在這里。
在線程上點(diǎn)擊右鍵可以凍結(jié)線程:
凍結(jié)線程也就是Pause線程,
凍結(jié)的線程可以被解凍,也就是Resume。
其他的窗口:
調(diào)試->窗口->模塊:可以看到當(dāng)前程序加載的所有模塊。
調(diào)試->窗口->進(jìn)程:
調(diào)試->窗口->反匯編:
調(diào)試->窗口->寄存器:
調(diào)試->窗口->調(diào)用堆棧:
調(diào)用堆棧窗口是比較常用的窗口:
上圖表示先調(diào)用A方法,接著B(niǎo)方法,接著C方法。
也可以認(rèn)為是C方法是B調(diào)用,而B(niǎo)方法是A調(diào)用的。
其他窗口比較常用,就不介紹了,是不是有一些你沒(méi)用到的窗口呢?
- VSCode調(diào)試C#程序及附缺失.dll文件的解決辦法
- C#客戶端程序Visual Studio遠(yuǎn)程調(diào)試的方法詳解
- C#動(dòng)態(tài)加載組件后如何在開(kāi)發(fā)環(huán)境中調(diào)試詳解
- C#中利用斷點(diǎn)操作調(diào)試程序的步驟詳解
- C# Web應(yīng)用調(diào)試開(kāi)啟外部訪問(wèn)步驟解析
- C#使用Windows Service的簡(jiǎn)單教程(創(chuàng)建、安裝、卸載、調(diào)試)
- C# 動(dòng)態(tài)編譯、動(dòng)態(tài)執(zhí)行、動(dòng)態(tài)調(diào)試
- c# 代碼調(diào)試技巧和如何遠(yuǎn)程調(diào)試
相關(guān)文章
基于c# Task自己動(dòng)手寫(xiě)個(gè)異步IO函數(shù)
這篇文章主要介紹了如何基于c# Task自己動(dòng)手寫(xiě)個(gè)異步IO函數(shù),幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-03-03Unity3D基于OnGUI實(shí)時(shí)顯示FPS
這篇文章主要介紹了Unity3D基于OnGUI實(shí)時(shí)顯示FPS,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11C#解碼base64編碼二進(jìn)制數(shù)據(jù)的方法
這篇文章主要介紹了C#解碼base64編碼二進(jìn)制數(shù)據(jù)的方法,涉及C#中Convert類的靜態(tài)方法Convert.FromBase64String使用技巧,需要的朋友可以參考下2015-04-04C#使用ILGenerator動(dòng)態(tài)生成函數(shù)的簡(jiǎn)單代碼
這篇文章主要介紹了C#使用ILGenerator動(dòng)態(tài)生成函數(shù)的簡(jiǎn)單代碼,需要的朋友可以參考下2017-08-08淺析WPF中控件拖拽與拖動(dòng)的實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了如何在WPF中實(shí)現(xiàn)控件拖拽與拖動(dòng)的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12