Làm cách nào để gỡ lỗi một chủ đề trong Visual Studio?


254

Tôi có một giải pháp với một số dự án. Có một số điểm dừng trong các dự án khác nhau. Tôi muốn theo dõi luồng đầu tiên đánh vào một trong những điểm dừng này và tiếp tục truy tìm luồng duy nhất đó mặc dù các luồng khác nhập vào cùng một khối mã.

Tôi biết điều này có thể thông qua việc xác định một điều kiện trên điểm dừng, nghĩa là, tên luồng = ... hoặc luồng Id = ... nhưng trường hợp của tôi là một ứng dụng ASP.NET tải nặng và ngay khi tôi đính kèm với w3wp.exenhiều chủ đề sẽ đạt điểm dừng. Tôi cần một số thứ như a ThreadLocal<break-point>.

Có thể không? Nếu vậy thì thế nào?


7
@Paolo: Ứng dụng web này hoạt động như trái tim của một trang trại web lớn và tình huống lỗi không thể bắt chước trong các kịch bản thử nghiệm.
Xaqron

Đối với VS 2019 có lẽ bạn nên thử điều này: stackoverflow.com/a/61868591/8579563
Gozo

Câu trả lời:


150

Chủ đề đóng băng / tan băng là một cách không chính xác vì các chủ đề khác không thực thi bất kỳ mã nào.

Cách chính xác và hữu dụng nhất là:

  1. Nhấn Ctrl + A trong cửa sổ điểm dừng (chọn tất cả điểm dừng).
  2. Nhấp chuột phải và chọn "Bộ lọc ...".
  3. Nhập "ThreadId = (id chủ đề hiện tại)".

Trong Visual Studio 2015 và mới hơn, quy trình tương tự:

  1. Nhấn Ctrl + A trong cửa sổ điểm dừng (chọn tất cả điểm dừng).
  2. Nhấp chuột phải và chọn "Cài đặt ...".
  3. Kiểm tra "Điều kiện" và chọn "Bộ lọc" trong danh sách thả xuống
  4. Nhập "ThreadId = (id chủ đề hiện tại)".

Vì vậy, tất cả các luồng được thực thi, nhưng trình gỡ lỗi chỉ truy cập vào luồng hiện tại.


51
Điều này có ngăn lệnh gỡ lỗi "Bước" vào các luồng khác không? Đó là một vấn đề lớn mà tôi có. Tôi đang bước qua chủ đề của mình và đột nhiên tôi ở một phần mã hoàn toàn không liên quan. Tôi không còn phát triển trong Visual Studio, vì vậy tôi không thể kiểm tra.
Matt Faus

8
Nhấp chuột phải vào cửa sổ điểm dừng không có lệnh "bộ lọc" ... và làm thế nào để bạn tìm ra Id luồng hiện tại? - Bạn đang đi đến cửa sổ ngay lập tức và gõ System.Threading.Thread.CurrentThread.ManagedThreadIdhoặc một cái gì đó?
BrainSlugs83

5
Trong VS của tôi (2015, Phiên bản cộng đồng), không thể sửa đổi Cài đặt của nhiều điểm dừng cùng một lúc. Do đó, Bộ lọc chỉ có thể được đặt từng cái một.
robert4

5
Tôi đã gặp vấn đề này mãi mãi và tôi có thể thề với công việc cuối cùng của mình với nó Tôi bắt đầu tự hỏi nếu tôi mơ thấy nó.
stu

7
-1 bởi vì điều này chỉ cho phép các điểm dừng, nhưng không thực sự gỡ lỗi: bước qua / bước vào không hoạt động theo cách này để gỡ lỗi một luồng.
Serge Rogatch

338

Đây là những gì tôi đã làm:

  1. Đặt điểm dừng có điều kiện mà tôi biết sẽ chỉ đánh vào luồng mà tôi đang tìm kiếm.

  2. Khi điểm dừng chạm và bạn đang ở trong luồng bạn muốn, trong cửa sổ Chủ đề của Visual Studio (trong khi gỡ lỗi, Gỡ lỗi -> Windows -> Chủ đề), Ctrl+ A(để chọn tất cả các luồng), sau đó Ctrl+ bấm vào chuỗi bạn đang hiện . Bạn nên có tất cả các chủ đề ngoại trừ chủ đề bạn muốn gỡ lỗi được chọn.

  3. Nhấp chuột phải và chọn "Đóng băng".

Bây giờ, Visual Studio sẽ chỉ bước qua chuỗi tan băng. Nó dường như chậm hơn nhiều khi làm điều này, có lẽ bởi vì nó phải lặp qua tất cả các luồng bị đóng băng, nhưng nó mang lại sự tỉnh táo cho việc gỡ lỗi đa luồng của tôi.


1
Điều này không phù hợp với tôi trong bối cảnh tôi có khoảng 8 nhiệm vụ đang chạy trong các luồng khác nhau. Tôi đóng băng tất cả các luồng khác và "bước qua" nhưng IDE đóng băng một lúc, sau đó nhảy sang một luồng khác.
Meta-Knight

3
@Diego: Tôi không làm việc với dự án nữa nhưng nếu nó sẽ đóng băng tất cả các luồng trừ một luồng, nó sẽ thay đổi kịch bản gây ra lỗi, vì các luồng là bổ sung trong tình huống lỗi. Mặc dù đây là một giải pháp tao nhã, nhưng có vẻ như tính năng này nên được nhúng vào VS.
Xaqron

3
@ Meta-Knight Bạn nên đóng băng tất cả các luồng trừ Chủ đề chính. Nếu bạn làm như thế thì IDE này sẽ không bị đóng băng
Alex Zhukovskiy

15

Tôi vừa phát hành một tiện ích mở rộng Visual Studio 2010+ thực hiện chính xác những gì bạn đang tìm kiếm. Và nó miễn phí :).

Trình bày

Tiện ích mở rộng Visual Studio này thêm hai phím tắt và nút thanh công cụ để cho phép các nhà phát triển dễ dàng tập trung vào các luồng đơn trong khi gỡ lỗi các ứng dụng đa luồng.

Nó giảm đáng kể nhu cầu đi vào cửa sổ Chủ đề một cách thủ công để đóng băng / làm tan tất cả các chủ đề nhưng một trong những chủ đề cần phải tuân theo, và do đó giúp cải thiện năng suất.

Đặc trưng

Hạn chế thực hiện thêm cho chủ đề hiện tại. Sẽ đóng băng tất cả các chủ đề khác. Phím tắt: CTRL + T + T hoặc nút Bông tuyết. Chuyển sang chuỗi đơn tiếp theo (dựa trên ID). Sẽ thay đổi chủ đề hiện tại và đóng băng tất cả các chủ đề khác. Phím tắt: CTRL + T + J hoặc nút Tiếp theo.

Kiểm tra nó ở đây trên Thư viện , trên trang chính thức hoặc kho lưu trữ Github .


Phiên bản nào của VS bạn đang sử dụng?
Erwin Mayer

Tôi đã cài đặt tiện ích mở rộng nhưng không quản lý để làm cho nó hoạt động (đối với dự án hiện tại của tôi, tôi sử dụng VS2010). [Theo cách tôi nghĩ là một vấn đề với các luồng hoạt động chỉ xảy ra khi các luồng được tạo, đó có thể là hành vi tiêu chuẩn nên tôi đã xóa nhận xét trước đó của mình].
lau

3
Tôi sẽ kiểm tra cái này Bạn có thể là người duy nhất trên hành tinh đã thực hiện bất kỳ nỗ lực nào để giải quyết một trong những thất bại gỡ lỗi lớn nhất của microsoft.
stu

than ôi, nó sẽ không cài đặt vào vs2012. Bạn có phiên bản mới hơn hay bạn sẽ chia sẻ mã nguồn để tôi có thể tự xây dựng nó?
stu

@stu Mã nguồn có trên Codeplex tại đây: singlethread.codeplex.com nó sẽ hoạt động trên VS 2012 và VS 2013 nhưng tôi chưa cập nhật nó (không ai yêu cầu và tôi không có nhu cầu). Nếu bạn có thể làm cho nó hoạt động dễ dàng với VS 2012+ và thực hiện cam kết trên Codeplex thì tôi cũng có thể đẩy nó vào Thư viện.
Erwin Mayer

13

Nếu nhiều luồng được sinh ra như đối với một ứng dụng web, câu trả lời của @MattFaus sẽ không hoạt động. những gì tôi đã làm thay vì sau đây

  • Thiết lập một điểm dừng để làm gián đoạn chuỗi trong chức năng tôi muốn.
  • Khi luồng đã đến điểm dừng và bị tạm dừng, tôi xóa điểm dừng và tiếp tục gỡ lỗi bằng F8, F10 và F11, để các luồng khác có thể chạy.

Sau khi đọc tất cả các anserw hàng đầu, cách giải quyết này đã làm việc cho tôi.
Swanand Pangam

9

Một cách tiếp cận hơi khác mà tôi đã sử dụng:

  1. Tạo một điểm dừng bình thường và để nó bị tấn công
  2. Nhìn vào cửa sổ chủ đề của bạn để biết ID luồng được quản lý mà bạn hiện đang gỡ lỗi
  3. Nhấp chuột phải vào điểm dừng của bạn trong cửa sổ điểm dừng và bộ lọc chọn
  4. Nhập ThreadId = xxx trong đó xxx là ID luồng từ 2
  5. Bây giờ bạn có thể gỡ lỗi mà không dừng các luồng khác và không có chúng chạm vào điểm dừng của bạn

Điều này giả định rằng bạn có thời gian để làm điều trên trước khi một luồng thứ hai chạm đến điểm dừng của bạn. Nếu không và các luồng khác chạm vào điểm dừng của bạn trước khi bạn thực hiện các thao tác trên, bạn có thể nhấp chuột phải vào cửa sổ chuỗi và chọn đóng băng.


3
+1. "Điều này giả định rằng bạn có thời gian ... trước khi một luồng thứ hai chạm đến điểm dừng của bạn". Tôi bọc một dấu chấm phẩy trong một khóa và đặt một điểm dừng trên dấu chấm phẩy. Khi điểm dừng được chạm lần đầu tiên, tôi vô hiệu hóa điểm dừng. Không có chủ đề khác có thể đi vào do khóa. lock(m_someObject) { ; }
bluedog

Để tiết kiệm cho bạn một Google, cửa sổ chủ đề được tìm thấy trong Debug> Windows> Chủ đề.
Gabe

2

Trong VS 2019:

  1. Đặt điểm dừng ở đâu đó.
  2. Nhấn F5 (Tiếp tục) cho đến khi chủ đề của bạn đến.
  3. Nhấp vào điểm dừng để loại bỏ nó.
  4. Bạn có thể bước chuỗi với F10 hoặc F11.

Hoạt động cho VS2015 quá!
thời tiền sử

1

Tôi sẽ đề nghị thêm một phiên bản khác của ứng dụng trên máy chủ trực tiếp, trên cùng một phần cứng hoặc một máy mới (cụm nó) và sau đó chỉ gỡ lỗi phiên bản đó. Tôi sẽ không thêm một điểm dừng trong mã người dùng đang kích hoạt. Nếu đó không phải là một lựa chọn, tôi sẽ thêm dấu vết.

Tuy nhiên, nếu điều này là hoàn toàn cần thiết và bạn cần một chỉ số giải pháp, tôi chắc chắn rằng bạn có thể thêm một điểm dừng chỉ bị phá vỡ nếu yêu cầu đến từ địa chỉ IP của bạn. Bạn sẽ làm điều này bằng cách thêm một điểm dừng có điều kiện kiểm tra HttpContext.Request.UserHostAddress. Tuy nhiên, lưu ý rằng điều này làm chậm ứng dụng của bạn một cách đáng kể.


Đó là những gì tôi đã cố gắng. Vấn đề là trường hợp này không hoạt động trên cùng một tên miền (chạy trên IP hoặc tên miền khác) và điều này dẫn đến nhiều vấn đề về chứng chỉ (SSL, WCF, ...) và trong tình trạng lỗi thấp, tình trạng lỗi không bao giờ xảy ra!
Xaqron

Xin lỗi, tôi không chắc bạn đã thử cái nào trong số này, bạn đã thử điểm dừng có điều kiện chưa?
steinar

Có, tôi đặt tên cho họ dựa trên Id được quản lý của họ để đảm bảo tính duy nhất. Sau đó, thật khó để đoán Id nào được chỉ định và đặt điều kiện dựa trên phỏng đoán. Đôi khi đoán là gần và đôi khi phải mất một thời gian dài để bắt được chủ đề.
Xaqron

1

Nếu bạn không muốn dừng tất cả các luồng khác (có thể bạn đang đính kèm trình gỡ lỗi Visual Studio vào một ứng dụng đang chạy cần trả lời các yêu cầu), bạn có thể sử dụng macro tự động tạo và xóa điểm dừng.

Điều này được đề xuất trong câu trả lời cho câu hỏi Stack Overflow "Step over" khi gỡ lỗi các chương trình đa luồng trong Visual Studio .

Tuy nhiên, liên kết chỉ giải thích làm thế nào để gỡ lỗi từng dòng. Tôi khuyên bạn nên sửa đổi macro (nếu bạn cảm thấy thoải mái với nó) để làm cho nó sửa đổi tất cả các điểm dừng (ví dụ trong một phạm vi dòng nhất định) để chỉ dừng lại trên luồng hiện tại.


1

Tôi nghĩ rằng điều này hơi khác trong Visual Studio 2015. Họ đã thay đổi một số điều trong các điểm dừng, nhưng đây là cách áp dụng câu trả lời được chấp nhận từ hzdbyte (ở trên):

Trên điểm dừng trong lề mã hóa, Nhấp chuột phải> Điều kiện> Thay đổi từ 'Biểu thức có điều kiện' thành 'Bộ lọc'. Điều này sau đó cho phép bạn lọc theo ThreadId.

Ngoài ra, trên điểm dừng trong cửa sổ Điểm dừng, Nhấp chuột phải> Cài đặt> đánh dấu vào ô Điều kiện và thực hiện các thao tác trên.


1

Đặt Điều kiện điểm dừng bằng cách nhấp chuột phải vào thanh bên của dòng. Chọn "Điều kiện" và nhập thông tin sau với tên của chủ đề của bạn trong dấu ngoặc kép:

System.Threading.Thread.CảnThread.Name == "name_of_your_thread"

Ngoài ra, bạn có thể làm tương tự bằng cách lấy "ID được quản lý" của chuỗi từ Cửa sổ "Chủ đề" và sử dụng:

System.Threading.Thread.CảnThread.ManagedThreadId == your_managed_thread_id

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.