2012-12-26 25 views
5

Threaded được suppossed để tạo ra 4 thread riêng biệt và chờ cho đến khi chúng kết thúc. Mỗi thread ngủ trong một thời gian và kết thúc chỉ khi chia sẻ Mutex opbject không bị chiếm bởi một thread khác và sau đó báo hiệu máng một sự kiện mà nó đã hoàn thành (Đây là một phiên bản đơn giản của mã của tôi nhưng không thành công tại cùng một vị trí)WaitOne() chờ đợi mãi mãi mặc dù tất cả các sự kiện được kích hoạt

Nhưng những gì xảy ra là hầu hết thời gian các chủ đề chính sẽ chờ đợi mãi mãi tại một trong những WaitOne() dường như ngẫu nhiên.

Ngoài ra tôi đã phải bình luận ra một số phần của mã của tôi ra vì nó đã dẫn đến thậm chí hành vi bất ngờ hơn (Tức là bằng cách nào đó sau mỗi thread xong các chủ đề chính sẽ nhảy trở lại vào cho khoản và gây ra một IndexOutOfBounds)

class Threading 
{ 
    static Mutex CM; 
    static List<Manga> SharedList; 
    static ManualResetEvent CEvent = new ManualResetEvent(false); 
    static ManualResetEvent Event1 = new ManualResetEvent(false); 
    static ManualResetEvent Event2 = new ManualResetEvent(false); 
    static ManualResetEvent Event3 = new ManualResetEvent(false); 
    static ManualResetEvent Event4 = new ManualResetEvent(false); 

    public List<Manga> ThreadedMangaIndexCrawl(int MaxThreads) 
    { 
     CM = new Mutex(false); 
     SharedList = new List<Manga>(); 

     ManualResetEvent[] evs = new ManualResetEvent[4]; 
     evs[0] = Event1; // Event for t1 
     evs[1] = Event2; // Event for t2 
     evs[2] = Event3; // Event for t3 
     evs[3] = Event4; // Event for t4 

     /*for (int i = 0; i < MaxThreads + 1; i++) 
     { 
      if (i > MaxThreads) 
      { break; } 
      Thread t = new Thread(() => this.StartIndexCrawling(1,i,i+1,evs[i])); 
      t.Start(); 
     }*/ 
     int i = 0; 
     Thread t1 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i])); 
     t1.Name = "Thread" + i; 
     t1.Start(); 
     i++; 
     Thread t2 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i])); 
     t2.Name = "Thread" + i; 
     t2.Start(); 
     i++; 
     Thread t3 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i])); 
     t3.Name = "Thread" + i; 
     t3.Start(); 
     i++; 
     Thread t4 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i])); 
     t4.Name = "Thread" + i; 
     t4.Start(); 


     /* foreach (var e in evs) 
     { 
      e.WaitOne(); 

     }*/ 

     evs[0].WaitOne(); 
     evs[1].WaitOne(); 
     evs[2].WaitOne(); 
     evs[3].WaitOne(); 

     return SharedList; 
    } 

    void StartIndexCrawling(int Target, int Start, int End, ManualResetEvent E) 
    { 
     Thread.Sleep(1000); 
     CM.WaitOne(); 
     CM.ReleaseMutex(); 
     E.Set(); 
    } 
} 

Bất kỳ trợ giúp sẽ là tuyệt vời

+0

Bạn đang tạo nhiều hơn một trong các đối tượng này? Các thành viên tĩnh dường như khá nguy hiểm đối với một đối tượng không đơn lẻ. –

+0

Cân nhắc sử dụng [Tác vụ] (http://msdn.microsoft.com/en-us/library/dd270695 (v = vs.100) .aspx) để xóa logic này. – roken

+0

@roken: Tôi nghĩ rằng Nhiệm vụ sẽ không dọn dẹp luồng thực thi mà có, đây chỉ là một cấu trúc khác để thực hiện công việc async với nhiều người trợ giúp/mở rộng enat hơn – sll

Trả lời

7

Nhiều khả năng, tất cả bốn chủ đề sẽ thực hiện:

this.StartIndexCrawling(1, 3, 3 + 1, evs[4]); 

này đã làm với việc bạn sử dụng closu res. Tất cả bốn chủ đề sẽ được ràng buộc với biến i và sử dụng bất kỳ giá trị nào nó có khi mã được thực hiện (và không phải là giá trị khi đối tượng Thread được tạo).

Mã của bạn sẽ không hoạt động nếu tất cả bốn chuỗi sử dụng cùng một giá trị.

+0

Ngoài ra hãy kiểm tra bài đăng này http://stackoverflow.com/questions/271440/c-sharp-captured-variable-in-loop – sll

+0

Tôi sẽ bị damned. Đó là điều cuối cùng tôi cho là nguyên nhân. Nhưng tại sao các chủ đề thực hiện chính mình với i hiện tại và không phải là một trong những họ đã trough các thông số? // chỉnh sửa chỉ thấy liên kết sau khi đăng – user1927074

+0

Trong 'StartIndexCrawling' bạn có bản sao cục bộ của các giá trị. Nhưng mã cao nhất của chuỗi là hàm ẩn danh được xác định bởi việc đóng '() => this.StartIndexCrawling (1, i, i + 1, evs [i])'. Và mã này đề cập đến biến chia sẻ 'i'. Đó là cách đóng cửa hoạt động. – Codo

0

Xem câu trả lời của Codo.
Đây là những gì bạn nên làm để giải quyết:

int i = 0; 
    Thread t1 = new Thread(() => this.StartIndexCrawling(1, 0, 1, Event1)); 
    t1.Name = "Thread" + i; 
    t1.Start(); 
    i++; 
    Thread t2 = new Thread(() => this.StartIndexCrawling(1, 1, 2, Event2)); 
    t2.Name = "Thread" + i; 
    t2.Start(); 
    i++; 
    Thread t3 = new Thread(() => this.StartIndexCrawling(1, 2, 3, Event3)); 
    t3.Name = "Thread" + i; 
    t3.Start(); 
    i++; 
    Thread t4 = new Thread(() => this.StartIndexCrawling(1, 3, 4, Event4)); 
    t4.Name = "Thread" + i; 
    t4.Start(); 
Các vấn đề liên quan