2010-04-22 32 views
10

Kịch bản của chúng tôi là máy quét mạng.Trong .NET có một bộ lập lịch trình cho các chủ đề dài chạy không?

Kết nối với một nhóm máy chủ và quét chúng song song trong một thời gian sử dụng các chuỗi nền ưu tiên thấp.

Tôi muốn có thể lên lịch cho nhiều tác phẩm nhưng chỉ có bất kỳ số lượng nào được cho là mười hoặc bất kỳ số lượng máy chủ nào được quét song song. Ngay cả khi tôi tạo ra các chủ đề của riêng tôi, nhiều callback và goodness không đồng bộ khác sử dụng ThreadPool và cuối cùng tôi đã hết tài nguyên. Tôi nên xem MonoTorrent ...

Nếu tôi sử dụng THE ThreadPool, tôi có thể giới hạn đơn đăng ký của mình cho một số số để đủ cho phần còn lại của ứng dụng chạy trơn tru không?

Có một threadpool mà tôi có thể khởi tạo để n chủ đề sống lâu?

[Chỉnh sửa] Không ai có thể nhận thấy rằng tôi đã đưa ra một số nhận xét về một số câu trả lời vì vậy tôi sẽ thêm một vài điều ở đây.

  • Các chủ đề phải được hủy cả hai một cách duyên dáng và mạnh mẽ.
  • Chủ đề phải có mức độ ưu tiên thấp để thoát khỏi giao diện GUI.
  • Chủ đề đang chạy dài nhưng theo Thứ tự (phút) và không phải Thứ tự (ngày).

làm việc cho một loạt mục tiêu đặt ra về cơ bản là:

For each test 
    Probe target (work is done mostly on the target end of an SSH connection) 
    Compare probe result to expected result (work is done on engine machine) 
    Prepare results for host 

Ai đó có thể giải thích tại sao bằng cách sử dụng SmartThreadPool được đánh dấu wit ha tính hữu dụng tiêu cực?

+0

câu trả lời Jeff xương ức dường như thích hợp, mặc dù thay vì BackgroundWorker bạn có thể được tốt hơn off tạo riêng 'trường System.Threading.Thread' của bạn. Tuy nhiên, bạn cũng đề cập đến rằng ngay cả trong các chủ đề của riêng bạn, bạn đang chạy ra khỏi tài nguyên thread-pool vì các hoạt động không đồng bộ. Có lẽ bạn nên giải thích lý do tại sao bạn đang thực hiện các hoạt động không đồng bộ trong một chuỗi mà bạn đã dành riêng để chạy các hoạt động đó. –

+0

Sau một số tìm kiếm khác, tôi đã xem qua một ThreadPool http://smartthreadpool.codeplex.com/ khác có thể xảy ra tại chỗ. Tôi sử dụng công cụ asynch trong chuỗi công nhân để xử lý đầu ra và lỗi khi chúng xảy ra. Khi ứng dụng chạy, người dùng được cung cấp phản hồi để họ xem cách xa từng tác vụ. – LogicMagic

+0

Ứng dụng được viết bằng GTK # và mẫu MVC. Có một giao diện GUI khi một số sự kiện nhất định kích hoạt, luồng GUI được sắp xếp và được cập nhật.Việc quét không phải là ping đơn giản, ứng dụng là một máy quét xác thực xem xét cấu hình của các mục tiêu. Quá trình quét sẽ mất thời gian O (phút) để hoàn thành. cho mỗi máy chủ. Một số báo cáo máy chủ được thực hiện trên máy công cụ trên mỗi luồng máy chủ vì lý do hiển nhiên. Một quá trình được tạo ra cho mỗi kết nối mà có lẽ là tốn kém, nhưng so với phút nó không quan trọng. – LogicMagic

Trả lời

8

Trong .NET 4 bạn có tích hợp Task Parallel Library. Khi bạn tạo một Tác vụ mới (tóm tắt chuỗi mới), bạn có thể chỉ định Nhiệm vụ là chạy dài. Chúng tôi đã có những kinh nghiệm tốt với điều đó (ngày dài hơn là vài phút hoặc vài giờ).

Bạn cũng có thể sử dụng nó trong .NET 2 nhưng thực tế nó có phần mở rộng, hãy kiểm tra here.

Trong VS2010 Gỡ lỗi Ứng dụng song song dựa trên Tác vụ (không phải chủ đề) đã được cải thiện triệt để. Bạn nên sử dụng Tác vụ bất cứ khi nào có thể thay vì chuỗi thô. Vì nó cho phép bạn xử lý song song theo một cách thân thiện hơn theo hướng đối tượng.

CẬP NHẬT
Nhiệm vụ không được chỉ định như dài chạy, đang xếp hàng đợi vào hồ bơi thread (hoặc bất kỳ lịch trình khác cho rằng vấn đề).
Nhưng nếu một nhiệm vụ được quy định là dài chạy, nó chỉ tạo ra một độc Chủ đề, không hồ bơi thread được tham gia.

+0

Không TPL nằm trên đầu trang của ThreadPool? – LogicMagic

+0

Mục đích của TPL là thêm một lớp ý nghĩa có thể trừu tượng về luồng và lên lịch các nhiệm vụ khác nhau. Vẻ đẹp của TPL là bạn có thể chỉ định ** lịch biểu **. Lịch trình ** CÓ THỂ ** trên thực tế là nhóm chủ đề. Nhưng bạn cũng có thể xác định chính mình. Để biết thêm thông tin, hãy kiểm tra: http://bit.ly/aW4Lq4 và http://bit.ly/9VAkbf – ntziolis

5

CLR ThreadPool không thích hợp để thực hiện các tác vụ dài hạn: đó là để thực hiện các tác vụ ngắn trong đó chi phí tạo chuỗi sẽ gần như cao như thực thi chính phương thức đó. Như bạn đã thấy, bản thân .NET tiêu thụ chủ đề của luồng thread, bạn không thể dự trữ một khối của chúng cho chính mình vì sợ rằng bạn có nguy cơ bỏ đói thời gian chạy.

Lập biểu, điều chỉnh và hủy công việc là một vấn đề khác. Không có sẵn hồ bơi chuỗi công việc xếp hàng .NET khác, vì vậy bạn sẽ tự cuộn (tự mình quản lý số threads hoặc BackgroundWorkers) hoặc tìm một từ trước (Ami Bar's SmartThreadPool có vẻ đầy hứa hẹn, mặc dù bản thân tôi chưa tự sử dụng).

+0

Công nhân nền được cho là lập kế hoạch cho các tác vụ chạy dài trong khi vẫn giữ được giao diện người dùng. Họ không phải là sự lựa chọn đúng đắn cho luồng logic ứng dụng. – ntziolis

+0

@ntziolis - Tôi đồng ý, mặc dù chúng tôi không có đủ thông tin về ứng dụng để loại trừ hoàn toàn: một 'máy quét mạng' có thể có nghĩa là [ứng dụng GUI] (http://www.softperfect.com/products/networkscanner /). –

+0

Điều đó đúng, có thể người sáng tạo có thể thêm một số thông tin bổ sung? – ntziolis

1

Trong trường hợp cụ thể của bạn, tùy chọn tốt nhất sẽ không là chủ đề hoặc nhóm luồng hoặc công nhân nền, mà là mô hình lập trình không đồng bộ (BeginXXX, EndXXX) do khung công tác cung cấp.

Ưu điểm của việc sử dụng asynchronous model là ngăn xếp TcpIp sử dụng cuộc gọi lại bất cứ khi nào có dữ liệu để đọc và gọi lại tự động chạy trên một chuỗi từ nhóm chủ đề.

Sử dụng asynchronous model, bạn có thể kiểm soát số lượng yêu cầu cho mỗi khoảng thời gian bắt đầu và cũng có thể nếu bạn muốn bạn có thể bắt đầu tất cả yêu cầu từ chuỗi ưu tiên thấp hơn trong khi xử lý yêu cầu trên chuỗi ưu tiên bình thường. ít nhất có thể trong Hàng đợi Tcp nội bộ của ngăn xếp mạng.

Asynchronous Client Socket Example - MSDN

P.S. Đối với nhiều công việc đồng thời và dài chạy mà không làm allot tính toán nhưng chủ yếu là chờ đợi trên IO (mạng, đĩa, vv) tùy chọn tốt hơn luôn luôn là sử dụng một cơ chế gọi lại và không phải chủ đề.

1

Tôi muốn tạo trình quản lý chuỗi của riêng bạn. Trong ví dụ đơn giản sau, một Hàng đợi được sử dụng để giữ các chủ đề chờ đợi và một từ điển được sử dụng để giữ các chủ đề đang hoạt động, được khóa bởi ManagedThreadId. Khi một luồng kết thúc, nó tự xóa khỏi từ điển đang hoạt động và khởi chạy một luồng khác thông qua một cuộc gọi lại.

Bạn có thể thay đổi giới hạn chuỗi chạy tối đa từ giao diện người dùng, và bạn có thể chuyển thông tin bổ sung vào cuộc gọi lại ThreadDone để giám sát hiệu suất, v.v. Nếu chuỗi không thành công, thời gian chờ mạng, bạn có thể lắp lại vào hàng đợi . Thêm phương pháp kiểm soát thêm để Supervisor cho tạm dừng, dừng lại, vv

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

namespace ConsoleApplication1 
{ 
    public delegate void CallbackDelegate(int idArg); 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      new Supervisor().Run(); 
      Console.WriteLine("Done"); 
      Console.ReadKey(); 
     } 
    } 

    class Supervisor 
    { 
     Queue<System.Threading.Thread> waitingThreads = new Queue<System.Threading.Thread>(); 
     Dictionary<int, System.Threading.Thread> activeThreads = new Dictionary<int, System.Threading.Thread>(); 
     int maxRunningThreads = 10; 
     object locker = new object(); 
     volatile bool done; 

     public void Run() 
     { 
      // queue up some threads 
      for (int i = 0; i < 50; i++) 
      { 
       Thread newThread = new Thread(new Worker(ThreadDone).DoWork); 
       newThread.IsBackground = true; 
       waitingThreads.Enqueue(newThread); 
      } 
      LaunchWaitingThreads(); 
      while (!done) Thread.Sleep(200); 
     } 

     // keep starting waiting threads until we max out 
     void LaunchWaitingThreads() 
     { 
      lock (locker) 
      { 
       while ((activeThreads.Count < maxRunningThreads) && (waitingThreads.Count > 0)) 
       { 
        Thread nextThread = waitingThreads.Dequeue(); 
        activeThreads.Add(nextThread.ManagedThreadId, nextThread); 
        nextThread.Start(); 
        Console.WriteLine("Thread " + nextThread.ManagedThreadId.ToString() + " launched"); 
       } 
       done = (activeThreads.Count == 0) && (waitingThreads.Count == 0); 
      } 
     } 

     // this is called by each thread when it's done 
     void ThreadDone(int threadIdArg) 
     { 
      lock (locker) 
      { 
       // remove thread from active pool 
       activeThreads.Remove(threadIdArg); 
      } 
      Console.WriteLine("Thread " + threadIdArg.ToString() + " finished"); 
      LaunchWaitingThreads(); // this could instead be put in the wait loop at the end of Run() 
     } 
    } 

    class Worker 
    { 
     CallbackDelegate callback; 
     public Worker(CallbackDelegate callbackArg) 
     { 
      callback = callbackArg; 
     } 

     public void DoWork() 
     { 
      System.Threading.Thread.Sleep(new Random().Next(100, 1000)); 
      callback(System.Threading.Thread.CurrentThread.ManagedThreadId); 
     } 
    } 
} 
Các vấn đề liên quan