Bagaimana cara debug satu utas di Visual Studio?

254

Saya punya solusi dengan beberapa proyek. Ada beberapa break-point di berbagai proyek. Saya ingin melacak utas pertama mengenai salah satu break-point ini dan terus menelusuri utas tunggal tersebut meskipun ada utas lain yang memasuki blok kode yang sama.

Saya tahu ini dimungkinkan melalui mendefinisikan suatu kondisi pada break-point, yaitu, nama thread = ... atau utas = = tapi kasus saya adalah aplikasi ASP.NET yang sarat dengan muatan dan segera setelah saya lampirkan ke w3wp.exebanyak utas akan mencapai titik break. Saya butuh sesuatu seperti ThreadLocal<break-point>.

Apa itu mungkin? Jika ya, bagaimana caranya?

Xaqron
sumber
7
@ Paolo: Aplikasi web ini berfungsi sebagai jantung dari web farm besar dan situasi kereta tidak mungkin untuk ditiru dalam pengujian skenario.
Xaqron
Untuk VS 2019 mungkin Anda harus mencoba ini: stackoverflow.com/a/61868591/8579563
Gozo

Jawaban:

150

Membekukan / Mencairkan utas adalah cara yang salah karena utas lain tidak menjalankan kode apa pun.

Cara yang paling benar dan bermanfaat adalah:

  1. Tekan Ctrl + A di jendela breakpoints (pilih semua breakpoints).
  2. Klik kanan dan pilih "Filter ...".
  3. Masukkan "ThreadId = (id utas saat ini)".

Dalam Visual Studio 2015 dan yang lebih baru, prosesnya serupa:

  1. Tekan Ctrl + A di jendela breakpoints (pilih semua breakpoints).
  2. Klik kanan dan pilih "Pengaturan ...".
  3. Periksa "Ketentuan" dan pilih "Saring" di menu tarik-turun
  4. Masukkan "ThreadId = (id utas saat ini)".

Jadi semua utas dieksekusi, tetapi debugger hanya mengenai utas saat ini.

hzdbyte
sumber
51
Apakah ini mencegah perintah debugger "Langkah" memasuki utas lainnya? Itu adalah masalah besar yang saya miliki. Saya melangkah melalui utas saya dan tiba-tiba saya berada di bagian kode yang sama sekali tidak terkait. Saya tidak lagi berkembang di Visual Studio, jadi saya tidak bisa menguji.
Matt Faus
8
Mengklik kanan di jendela breakpoints tidak memiliki perintah "filter" ... dan bagaimana Anda mengetahui id utas saat ini? - Apakah Anda akan langsung ke jendela dan mengetik System.Threading.Thread.CurrentThread.ManagedThreadIdatau sesuatu?
BrainSlugs83
5
Dalam VS saya (2015, Edisi Komunitas) tidak mungkin untuk mengubah Pengaturan beberapa breakpoint sekaligus. Dengan demikian Filter dapat diatur hanya satu per satu.
robert4
5
Saya pernah mengalami masalah ini selamanya, dan saya bisa bersumpah pada pekerjaan terakhir saya, saya menemukan pengaturan yang membuat studio visual bekerja seperti gerhana di mana Anda akan tetap berpegang pada utas yang Anda kerjakan, tetapi saya tidak dapat menemukannya atau referensi apa pun untuk itu. Saya mulai bertanya-tanya apakah saya memimpikannya.
stu
7
-1 karena ini hanya memungkinkan untuk breakpoints, tetapi tidak untuk benar-benar men-debug: melangkahi / melangkah ke tidak bekerja dengan cara ini untuk men-debug satu utas.
Serge Rogatch
338

Inilah yang saya lakukan:

  1. Tetapkan titik istirahat bersyarat yang saya tahu hanya akan mengenai utas yang saya cari.

  2. Setelah breakpoint hits dan Anda berada di utas yang Anda inginkan, di jendela Visual Studio Threads (saat debugging, Debug -> Windows -> Threads), Ctrl+ A(untuk memilih semua utas), dan kemudian Ctrl+ klik utas yang saat ini Anda aktifkan . Anda harus memiliki semua utas kecuali yang ingin Anda debug dipilih.

  3. Klik kanan, dan pilih "Bekukan".

Sekarang, Visual Studio hanya akan melangkah melalui utas yang dicairkan. Tampaknya jauh lebih lambat ketika melakukan ini, mungkin karena ia harus melewati semua utas yang dibekukan, tetapi hal ini membawa kewarasan pada debugging multi-utas saya.

Matt Faus
sumber
1
Ini tidak berfungsi untuk saya dalam konteks di mana saya memiliki sekitar 8 tugas yang berjalan di utas yang berbeda. Saya membekukan semua utas lainnya dan "melangkahi" tetapi IDE membeku untuk sementara waktu, kemudian melompat ke utas lainnya.
Meta-Knight
3
@Diego: Saya tidak mengerjakan proyek lagi tetapi jika itu akan membekukan semua utas kecuali satu, itu akan mengubah skenario yang menyebabkan bug, karena utas saling melengkapi dalam situasi kereta. Meskipun ini adalah solusi yang elegan, tampaknya fitur ini harus tertanam ke dalam VS.
Xaqron
3
@ Meta-Knight Anda harus membekukan semua utas kecuali Utas Utama. Jika Anda mau IDE ini tidak akan dibekukan
Alex Zhukovskiy
15

Saya baru saja merilis ekstensi Visual Studio 2010+ yang melakukan persis apa yang Anda cari. Dan gratis :).

Presentasi

Ekstensi Visual Studio ini menambahkan dua pintasan dan tombol bilah alat untuk memungkinkan pengembang dengan mudah fokus pada utas tunggal saat men-debug aplikasi multi-utas.

Ini secara dramatis mengurangi kebutuhan untuk secara manual masuk ke jendela Threads untuk membekukan / mencairkan semua thread tetapi yang perlu diikuti, dan karenanya membantu meningkatkan produktivitas.

fitur

Batasi eksekusi lebih lanjut hanya untuk utas saat ini. Akan membekukan semua utas lainnya. Pintasan: tombol CTRL + T + T atau Snowflake. Beralih ke utas tunggal berikutnya (berdasarkan ID). Akan mengubah utas saat ini dan membekukan semua utas lainnya. Shortcut: tombol CTRL + T + J atau Next.

Lihat di sini di Galeri , di halaman resmi atau repositori Github .

Erwin Mayer
sumber
Versi VS mana yang Anda gunakan?
Erwin Mayer
Saya menginstal ekstensi, tetapi tidak berhasil membuatnya bekerja (untuk proyek saya saat ini, saya menggunakan VS2010). [Ngomong-ngomong, apa yang saya pikir masalah dengan utas menjadi aktif hanya terjadi ketika utas dibuat, mungkin itu adalah perilaku standar jadi saya menghapus komentar saya sebelumnya].
bersihkan
3
Saya akan memeriksanya. Anda mungkin satu-satunya orang di planet ini yang telah melakukan upaya apa pun untuk menyelesaikan salah satu kegagalan debugging terbesar microsoft.
stu
sayangnya, itu tidak akan diinstal pada vs2012. Apakah Anda memiliki versi yang lebih baru atau Anda akan membagikan kode sumber sehingga saya dapat membuatnya sendiri?
stu
@stu Kode sumbernya ada pada Codeplex di sini: singlethread.codeplex.com seharusnya bekerja pada VS 2012 dan VS 2013 tetapi saya belum memperbaruinya (tidak ada yang memintanya dan saya sendiri tidak membutuhkannya). Jika Anda dapat membuatnya bekerja dengan mudah dengan VS 2012+ dan membuat komit pada Codeplex maka saya dapat mendorongnya di Galeri juga.
Erwin Mayer
13

Jika beberapa utas sedang muncul untuk aplikasi web, jawaban @MattFaus tidak akan berfungsi. apa yang saya lakukan adalah sebagai berikut

  • Siapkan breakpoint untuk menginterupsi utas dalam fungsi yang saya inginkan.
  • Setelah utas sampai ke breakpoint dan dijeda, saya menghapus breakpoint dan melanjutkan debug menggunakan F8, F10 dan F11, sehingga utas lainnya dapat berjalan.
Mikaël Mayer
sumber
Setelah membaca semua jawaban teratas, solusi ini berhasil untuk saya.
Swanand Pangam
9

Pendekatan yang sedikit berbeda yang saya gunakan:

  1. Buat breakpoint normal dan biarkan terkena
  2. Lihat di jendela utas Anda untuk mengetahui ID utas yang dikelola yang sedang Anda debug
  3. Klik kanan breakpoint Anda di jendela breakpoints dan filter pemilih
  4. Masukkan ThreadId = xxx di mana xxx adalah ID utas dari 2
  5. Sekarang Anda dapat men-debug tanpa menghentikan utas lainnya dan tanpa menabrak breakpoint Anda

Ini mengasumsikan Anda punya waktu untuk melakukan hal di atas sebelum utas kedua mengenai breakpoint Anda. Jika tidak dan utas lainnya mengenai breakpoint Anda sebelum Anda melakukan hal di atas, Anda dapat mengeklik kanannya di jendela utas dan memilih membeku.

Mat
sumber
3
+1. "Ini mengasumsikan Anda punya waktu ... sebelum utas kedua mengenai breakpoint Anda". Saya membungkus titik koma di kunci dan meletakkan breakpoint di titik koma. Ketika breakpoint terkena pertama kali, saya menonaktifkan breakpoint. Tidak ada utas lain yang bisa masuk karena kunci. lock(m_someObject) { ; }
bluedog
Untuk menghemat Google, jendela utas ditemukan di Debug> Windows> Utas.
Gabe
2

Dalam VS 2019:

  1. Atur breakpoint di suatu tempat.
  2. Tekan F5 (Lanjutkan) sampai utas Anda muncul.
  3. Klik pada breakpoint untuk menghapusnya.
  4. Anda dapat melangkah utas dengan F10 atau F11.
Gozo
sumber
Bekerja untuk VS2015 juga!
prehistoricpenguin
1

Saya akan menyarankan untuk menambahkan instance aplikasi lain pada server langsung, baik pada perangkat keras yang sama atau mesin baru (klaster itu) dan kemudian debug hanya contoh itu. Saya tidak akan menambahkan breakpoint dalam kode yang dipicu pengguna. Jika itu bukan opsi, saya akan menambahkan lebih banyak penelusuran.

Namun, jika ini benar-benar diperlukan dan Anda memerlukan stat solusi, saya yakin Anda dapat menambahkan breakpoint yang hanya akan rusak jika permintaan berasal dari alamat IP Anda. Anda akan melakukan ini dengan menambahkan breakpoint bersyarat yang memeriksa HttpContext.Request.UserHostAddress. Namun perlu dicatat bahwa ini sangat memperlambat aplikasi Anda.

steinar
sumber
Itu yang saya coba. Masalahnya adalah instance ini tidak bekerja pada domain yang sama (berjalan pada IP atau domain lain) dan ini menyebabkan banyak masalah sertifikat (SSL, WCF, ...) dan juga di bawah beban rendah, situasi kereta tidak pernah terjadi!
Xaqron
Maaf, saya tidak yakin yang mana yang sudah Anda coba, sudahkah Anda mencoba breakpoint bersyarat?
steinar
Ya, saya menamai mereka berdasarkan ID terkelola mereka untuk memastikan keunikan. Maka sulit untuk menebak ID mana yang ditugaskan dan mengatur kondisi berdasarkan suatu tebakan. Terkadang tebakannya dekat dan terkadang butuh waktu lama untuk menangkap utasnya.
Xaqron
1

Jika Anda tidak ingin menghentikan semua utas lainnya (mungkin Anda melampirkan Visual Studio debugger ke aplikasi yang sedang berjalan yang perlu menjawab permintaan), Anda bisa menggunakan makro yang membuat dan menghapus breakpoint secara otomatis.

Ini disarankan dalam jawaban untuk pertanyaan Stack Overflow "Step over" ketika men- debug program multithreaded di Visual Studio .

Namun, tautan hanya menjelaskan cara men-debug baris demi baris. Saya sarankan Anda memodifikasi makro (jika Anda nyaman dengan itu) untuk membuatnya memodifikasi semua breakpoints (dalam rentang garis tertentu misalnya) untuk berhenti hanya pada utas saat ini.

kamaradclimber
sumber
1

Saya pikir ini sedikit berbeda di Visual Studio 2015. Mereka telah mengubah beberapa hal di breakpoints, tapi inilah cara menerapkan jawaban yang diterima dari hzdbyte (di atas):

Pada breakpoint di margin coding, Klik kanan> Ketentuan> Ubah dari 'Ekspresi Bersyarat' menjadi 'Filter'. Ini kemudian memungkinkan Anda untuk memfilter berdasarkan ThreadId.

Atau di breakpoint di jendela Breakpoints, Klik kanan> Pengaturan> centang kotak Ketentuan dan lakukan di atas.

Patelos
sumber
1

Tetapkan Kondisi Breakpoint dengan mengklik kanan bilah samping garis. Pilih "Kondisi" dan masukkan yang berikut ini dengan nama utas Anda dalam tanda kutip:

System.Threading.Thread.CurrentThread.Name == "name_of_your_thread"

Atau Anda dapat melakukan hal yang sama dengan mendapatkan "Managed ID" utas dari Jendela "Utas" dan menggunakan:

System.Threading.Thread.CurrentThread.ManagedThreadId == your_managed_thread_id

James Sheridan
sumber