2009-08-25 34 views
41

Tôi đang sử dụng phương pháp thread.Abort để xóa chuỗi nhưng không hoạt động. Có cách nào khác để chấm dứt thread?Làm thế nào để tiêu diệt một chuỗi ngay lập tức trong C#?

private void button1_Click(object sender, EventArgs e) 
{ 
    if (Receiver.IsAlive == true) 
    { 
     MessageBox.Show("Alive"); 
     Receiver.Abort(); 
    } 
    else 
    { 
     MessageBox.Show("Dead"); 
     Receiver.Start(); 
    } 
} 

Tôi đang sử dụng điều này nhưng mỗi lần tôi nhận trạng thái Alive, Receiver là chuỗi toàn cầu của tôi.

+10

Nguy hiểm, Will Robinson, Danger! Được ** rất ** nhút nhát bằng cách sử dụng Thread.Abort - hầu như luôn luôn là một ý tưởng tồi. –

+4

Sau đó, những gì nên được sử dụng để tiêu diệt các chủ đề? – Mobin

+3

Yêu cầu chỉ dừng lại và bỏ qua chuỗi từ thời điểm đó. – MSalters

Trả lời

58

Lý do thật khó để chỉ xóa một chuỗi là do nhà thiết kế ngôn ngữ muốn tránh sự cố sau: chuỗi của bạn mất khóa và sau đó bạn sẽ xóa nó trước khi nó có thể giải phóng. Bây giờ bất cứ ai cần khóa đó sẽ bị kẹt.

Những gì bạn phải làm là sử dụng một số biến toàn cục để yêu cầu chuỗi dừng lại. Bạn phải tự, trong mã chuỗi của bạn, hãy kiểm tra biến toàn cục đó và trả lại nếu bạn thấy nó cho biết bạn nên dừng lại.

+0

Tôi tự mình sử dụng cơ chế này. Đối với mã dựa trên giao diện người dùng, tôi đặt một biến toàn cầu và cho các dịch vụ tôi kiểm tra bảng cơ sở dữ liệu. Đẹp và có thể dự đoán được. –

+5

Nếu có thể, hãy sử dụng ManualResetEvent thay vì một biến, những gì chúng được thiết kế cho nó. –

+3

Tôi rất tò mò - làm thế nào để ManualResetEvent vượt trội hơn, để kiểm tra tình trạng chấm dứt sớm? Tôi hiểu chúng tốt hơn khi chúng ta phải chặn thứ gì đó, nhưng không có sự ngăn chặn ở đây. – redtuna

6

chuỗi sẽ bị giết khi hoàn thành công việc, vì vậy nếu bạn đang sử dụng vòng lặp hoặc thứ khác, bạn nên chuyển biến cho chuỗi để dừng vòng lặp sau khi chuỗi đó được hoàn tất.

4

C# Thread.Abort KHÔNG được đảm bảo để hủy bỏ chủ đề ngay lập tức. Nó có thể sẽ làm việc khi một thread gọi Abort trên chính nó nhưng không phải khi một thread gọi khác.

hãy tham khảo tài liệu: http://msdn.microsoft.com/en-us/library/ty8d3wta.aspx

tôi đã phải đối mặt với vấn đề này cụ tương tác với phần cứng bằng văn bản - bạn muốn dừng lại ngay lập tức, nhưng nó không được đảm bảo. Tôi thường sử dụng một số cờ hoặc logic khác như vậy để ngăn chặn thực hiện các phần của mã chạy trên một thread (và mà tôi không muốn được thực hiện trên abort - tricky).

14

Trước tiên, bạn nên có một số phương pháp đã đồng ý kết thúc chuỗi. Ví dụ: run_ có giá trị mà luồng có thể kiểm tra và tuân thủ.

Mã chủ đề chính của bạn nên được bao bọc trong một khối ngoại lệ để bắt cả ThreadInterruptException và ThreadAbortException sẽ dọn sạch luồng trên lối ra.

Trong trường hợp ThreadInterruptException bạn có thể kiểm tra biến running_ để xem bạn có nên tiếp tục không. Trong trường hợp của ThreadAbortException bạn nên dọn dẹp ngay lập tức và thoát khỏi thủ tục thread.

Mã mà cố gắng để ngăn chặn các chủ đề nên làm như sau:

running_ = false; 
threadInstance_.Interrupt(); 
if(!threadInstance_.Join(2000)) { // or an agreed resonable time 
    threadInstance_.Abort(); 
} 
+2

Đây là câu trả lời duy nhất có thể chấp nhận được từ quan điểm của tôi. Có, trước tiên bạn cần một biến cần lưu ý khi chuỗi có thể thoát nhưng nếu bạn đang chặn bên trong chuỗi, bạn có thể không bao giờ có cơ hội kiểm tra biến đó. Có cần phải có một cách khác để làm gián đoạn một luồng bị chặn và câu trả lời này giải quyết được vấn đề của tôi. Cảm ơn! – CramerTV

+0

Nếu 'threadInstance_.Interrupt()' kết thúc chuỗi nhanh, 'threadInstance_.Join' sẽ ném * System.Threading.ThreadStateException: Chủ đề chưa được bắt đầu * – Hannobo

24

Bạn có thể giết chết ngay lập tức thực hiện nó theo cách đó:

private Thread _myThread = new Thread(SomeThreadMethod); 

private void SomeThreadMethod() 
{ 
    // do whatever you want 
} 

[SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] 
private void KillTheThread() 
{ 
    _myThread.Abort(); 
} 

tôi luôn luôn sử dụng nó và làm việc cho tôi:)

+0

Nhưng xem http://stackoverflow.com/a/1560567/199364 và các câu trả lời khác mô tả lý do tại sao thread.abort là mạo hiểm. – ToolmakerSteve

+2

[Câu trả lời của Adrian Regan] (http://stackoverflow.com/a/1327377/199364) là một cách MUCH an toàn hơn để sử dụng 'Hủy bỏ '- như một phương sách cuối cùng nếu một sợi không chết. – ToolmakerSteve

-1
private void ResumeButton_Click(object sender, RoutedEventArgs e) 
    { 
     Task.Factory.StartNew(() => 
     { 
      Application.Current.Resources["AutoPilotThreadStatus"] = true; 
      Thread.CurrentThread.Name = "ResumeAutoPilot"; 
      Thread.CurrentThread.IsBackground = true; 
      AutoPilotHandler.ResumeAutoPilot(); 
     }); 
    } 

    public static void ResumeAutoPilot() 
    { 
     while ((bool)Application.Current.Resources["AutoPilotThreadStatus"]) 
     { 
      CheckAutoPilotThreadStatus(); 
      var searchYoutube = YoutubeHandler.Search("small truck"); 
      CheckAutoPilotThreadStatus(); 
      SaveVideosToDatabase(searchYoutube); 
      CheckAutoPilotThreadStatus(); 
     } 
    } 

    public static void CheckAutoPilotThreadStatus() 
    { 
     if (!(bool)Application.Current.Resources["AutoPilotThreadStatus"]) 
     { 
      KillCurrentThread(); 
     } 
    } 

    public static void KillCurrentThread() 
    { 
     Thread.CurrentThread.Abort(); 
    } 
+3

Một ví dụ hoàn hảo về cách sử dụng tài nguyên ứng dụng. –

Các vấn đề liên quan