2009-07-31 26 views
5

Tôi đang viết một chương trình mà tôi thường bắt đầu năm luồng. Các luồng trả về theo thứ tự không xác định. Mỗi thread đang gọi một phương thức trả về một List.Các chủ đề trả về dữ liệu trong .NET

tôi đang làm điều này:

var masterList = List<string>();  
foreach (var threadParam in threadParams) 
{ 
    var expression = threadParam ; 
    ThreadStart sub =() => MyMethod(expressions); 
    var thread = new Thread(sub) 
    { 
     Name = expression 
    }; 

    listThreads.Add(thread); 
    thread.Start(); 
} 

var abort = true; 
while (abort) //Wait until all threads finish 
{ 
    var count = 0; 
    foreach (var list in listThreads) 
    { 
     if (!list.IsAlive) 
     { 
      count++; 
     } 
    } 

    if (count == listThreads.Count) 
    { 
     abort = false; 
    } 
} 

Vì vậy, đây là vấn đề:

Mỗi thread khi nó chấm dứt trả về một danh sách Tôi muốn gắn masterList tuyên bố trước đó.

Làm cách nào để thực hiện điều này?

Ngoài ra tôi biết có phải là một cách tốt hơn so với bên dưới để chờ đợi cho tất cả các chủ đề để kết thúc

var abort = true; 
while (abort) //Wait until all threads finish 
{ 
    var count = 0; 
    foreach (var list in listThreads) 
    { 
     if (!list.IsAlive) 
     { 
      count++; 
     } 
    } 

    if (count == listThreads.Count) 
    { 
     abort = false; 
    } 
} 

Trả lời

14

Sử dụng một WaitHandle


Dưới đây là một Ví dụ:

using System; 
using System.Threading; 

class ThreadSleeper 
{ 
    int seconds; 
    AutoResetEvent napDone = new AutoResetEvent(false); 

    private ThreadSleeper(int seconds) 
    { 
     this.seconds = seconds; 
    } 

    public void Nap() 
    { 
     Console.WriteLine("Napping {0} seconds", seconds); 
     Thread.Sleep(seconds * 1000); 
     Console.WriteLine("{0} second nap finished", seconds); 
     napDone.Set(); 
    } 

    public static WaitHandle DoSleep(int seconds) 
    { 
     ThreadSleeper ts = new ThreadSleeper(seconds); 
     Thread thread = new Thread(new ThreadStart(ts.Nap)); 
     thread.Start(); 
     return(ts.napDone); 
    } 
} 

public class OperationsThreadsWaitingwithWaitHandle 
{ 
    public static void Main() 
    { 
     WaitHandle[] waits = new WaitHandle[2]; 
     waits[0] = ThreadSleeper.DoSleep(8); 
     waits[1] = ThreadSleeper.DoSleep(4); 

     Console.WriteLine("Waiting for threads to finish"); 
     WaitHandle.WaitAll(waits); 
     Console.WriteLine("Threads finished"); 
    } 
} 

Liên kết để kiểm tra:

+1

Ý tưởng tương tự như của tôi ... nhưng một cách trả lời tốt hơn :( –

0

Kiểm tra các lớp WaitHandle và WaitHandle.WaitAll (Tôi đã sử dụng lớp ManualResetEvent trong một số mã của tôi cho WaitHandle nhưng nó chỉ là một ví dụ. Tôi không biết nếu có cái gì tốt hơn cho tình hình của bạn). Tắt tất cả năm luồng, cung cấp cho họ tham chiếu đến danh sách chính của bạn, khóa danh sách này khi thêm vào, sau đó hoàn thành tín hiệu. Sử dụng WaitHandle.WaitAll để chặn cho đến khi tất cả năm đã báo hiệu hoàn thành.

2

Cách tốt nhất là đặt từng chủ đề thành đối tượng riêng. Không có bất kỳ xen kẽ với các đối tượng khác, tất cả các bạn làm là xây dựng nó (đi qua các biến), thêm mình như một người nghe và bắt đầu nó.

Khi hoàn thành, nó lưu trữ các giá trị trong biến thành viên và thông báo cho người nghe của bạn.

Trình nghe của bạn có thể truy xuất các giá trị lúc rảnh rỗi.

Phím tắt rõ ràng, trở về các giá trị trực tiếp đến người nghe, làm việc nhưng bạn có thể tìm thấy phiên bản này linh hoạt hơn sau (và thực sự không nhiều code)

1

Bạn cũng có thể sử dụng các đại biểu thông thường và APM.

Lưu ý rằng mẫu bạn mô tả thường được mô tả là Future, một công việc nền hứa hẹn sẽ trả về một cái gì đó sau này (lợi tức đầu tư nếu bạn có thể).

Đây là ví dụ ngắn, dưới dạng chương trình bảng điều khiển.

Output:

sequential: 3224 ms 
parallel: 2074 ms 

Dĩ nhiên, vì tôi không xây dựng chủ đề rõ ràng, tôi rời khỏi nó vào hệ thống threadpool để tìm ra bao nhiêu bài để chạy song song.

Ngoài ra còn có các quy định để được biết khi đề nền được hoàn thành, thông qua một phương pháp gọi lại, cũng như hỗ trợ WaitHandle để kiểm tra một cách rõ ràng và chờ đợi với thời gian chờ vv

Và nguồn:

using System; 
using System.Collections.Generic; 
using System.Threading; 
using System.Diagnostics; 

namespace SO1215227 
{ 
    public class Program 
    { 
     public static void Main() 
     { 
      Stopwatch sw = new Stopwatch(); 
      sw.Start(); 
      var list1 = Sequence(1, 100); 
      var list2 = Sequence(101, 200); 
      var list3 = Sequence(201, 300); 
      sw.Stop(); 
      Console.Out.WriteLine("sequential: " + sw.ElapsedMilliseconds + " ms"); 
      sw.Reset(); 

      Func<Int32, Int32, List<Int32>> listProducer = Sequence; 
      sw.Start(); 
      var list1Background = listProducer.BeginInvoke(1, 100, null, null); 
      var list2Background = listProducer.BeginInvoke(101, 200, null, null); 
      var list3Background = listProducer.BeginInvoke(201, 300, null, null); 

      list1 = listProducer.EndInvoke(list1Background); 
      list2 = listProducer.EndInvoke(list2Background); 
      list3 = listProducer.EndInvoke(list3Background); 
      sw.Stop(); 
      Console.Out.WriteLine("parallel: " + sw.ElapsedMilliseconds + " ms"); 

      Console.Out.Write("Press enter to exit..."); 
      Console.In.ReadLine(); 
     } 

     private static List<Int32> Sequence(Int32 from, Int32 to) 
     { 
      List<Int32> result = new List<Int32>(); 
      for (Int32 index = from; index <= to; index++) 
      { 
       result.Add(index); 
       Thread.Sleep(10); // simulate I/O wait 
      } 
      return result; 
     } 
    } 
} 
Các vấn đề liên quan