2011-11-07 6 views
13

Từ những gì tôi có thể nói tôi có các thông tin gây hiểu lầm. Tôi cần phải có một sợi riêng biệt chạy trong nền.Cách đảm bảo một chủ đề mới được tạo khi sử dụng phương thức Task.StartNew

Tại thời điểm này tôi làm điều đó như thế này:

var task = Task.Factory.StartNew 
     (CheckFiles 
      , cancelCheckFile.Token 
      , TaskCreationOptions.LongRunning 
      , TaskScheduler.Default);//Check for files on another thread 

private void CheckFiles() 
{ 
    while (!cancelCheckFile.Token.IsCancellationRequested) 
    { 
     //do stuff 
    } 
} 

này luôn tạo ra một thread mới đối với tôi. Tuy nhiên sau nhiều cuộc thảo luận ngay cả khi nó được đánh dấu là LongRunning không đảm bảo rằng một chuỗi mới sẽ được tạo ra.

Trong quá khứ tôi đã làm một cái gì đó như thế này:

thQueueChecker = new Thread(new ThreadStart(CheckQueue)); 
thQueueChecker.IsBackground = true; 
thQueueChecker.Name = "CheckQueues" + DateTime.Now.Ticks.ToString(); 
thQueueChecker.Start(); 


private void CheckQueue() 
{ 
    while (!ProgramEnding) 
    { 
      //do stuff 
    } 
} 

Bạn có khuyên tôi quay trở lại phương pháp này để đảm bảo một chủ đề mới được sử dụng?

+0

'LongRunning' chỉ là gợi ý cho trình lên lịch - nếu bạn hoàn toàn phải luôn có Chủ đề mới, bạn sẽ phải tạo một chủ đề mới. –

+0

Ưa thích thêm câu trả lời đó? – Jon

+0

Cảm ơn bạn Jon :) –

Trả lời

5

LongRunning chỉ là gợi ý cho trình lên lịch - nếu bạn hoàn toàn phải luôn có một Chủ đề mới, bạn sẽ phải tạo một chủ đề mới.

+1

Tôi nghĩ đây là câu trả lời đúng. Tôi thích sự trừu tượng của các chủ đề bằng cách sử dụng Tác vụ nhưng không ai có thể đảm bảo một chủ đề mới. Henk nói tôi nên để nó làm những gì tôi muốn nhưng điều này không đảm bảo một chủ đề mới. – Jon

+0

Bạn có nghĩ rằng những bình luận của Henk gợi ý rằng tôi đang đi sai đường là hợp lệ và nếu tôi muốn biết/tìm hiểu thêm – Jon

+0

Tôi nghĩ sự nhầm lẫn là về những từ như "bảo đảm". Tùy chọn 'LongRunning' không được" đảm bảo "để làm bất cứ điều gì cả. Tuy nhiên, TaskScheduler mặc định trong .NET 4 không tạo ra một luồng mới và đó là * không * để thay đổi. Sử dụng Task là một trừu tượng làm cho mã dễ dàng hơn, nhưng bạn sẽ mất kiểm soát. Nếu nó thực sự quan trọng đối với bạn, thì bạn luôn có thể viết một TaskScheduler đảm bảo một Thread mới và có tốt nhất của cả hai thế giới :) –

3

Bạn sẽ phải chỉ định lý do tại sao bạn "luôn cần một chuỗi riêng biệt".

void Main() 
{ 
    var task = Task.Factory.StartNew(CheckFiles, 
    cancelCheckFile.Token, 
    TaskCreationOptions.LongRunning, 
    TaskScheduler.Default); 

    task.Wait(); 
} 

Trình lên lịch thông minh sẽ sử dụng 1 chuỗi tại đây. Tại sao phải không?


Nhưng nói chung phương thức CheckFiles() sẽ được thực thi trên chuỗi khác (hơn gọi). Vấn đề là liệu luồng đó có được tạo ra đặc biệt hay nó có thể được thực hiện trên một số luồng (liên tiếp).

Khi bạn đang sử dụng Công việc, bạn từ bỏ quyền kiểm soát Chủ đề. Và đó phải là một điều tốt.

+0

Tôi muốn một chủ đề riêng biệt để ghi vào tập tin trên một chủ đề khác để các chủ đề gọi là trái để làm những gì nó muốn. Tôi có thể muốn một thread khác để xử lý dữ liệu nhận được bởi một socket. Trong cả hai trường hợp, dữ liệu sẽ được thêm vào hàng đợi và sau đó dequeued trên thread khác để lại thread gọi miễn phí để làm những việc khác – Jon

+0

Sau đó, lịch trình sẽ làm chính xác những gì bạn cần nếu bạn chỉ để cho nó. –

+0

Nhưng làm thế nào tôi có thể đảm bảo điều đó. Làm thế nào để bạn biết lịch trình sẽ làm điều đó cho tôi trên một sợi khác? Điều khác mà tôi không chỉ định và bạn làm là task.Wait. Như tôi muốn nó trên một chủ đề tôi không Chờ() – Jon

15

Trình lập lịch tác vụ mặc định ThreadPoolTaskScheduler thực sự luôn tạo một chuỗi mới cho tác vụ chạy dài. Nó không sử dụng các hồ bơi thread như bạn có thể nhìn thấy. Nó không khác với cách tiếp cận thủ công để tạo chủ đề một mình. Về lý thuyết nó có thể xảy ra rằng bộ lập lịch trình của .NET 4.5 thực hiện điều gì đó khác biệt nhưng trong thực tế nó không có khả năng thay đổi.

protected internal override void QueueTask(Task task) 
{  
    if ((task.Options & TaskCreationOptions.LongRunning) != TaskCreationOptions.None) 
    { 
    new Thread(s_longRunningThreadWork) { IsBackground = true }.Start(task); 
    } 
    else 
    { 
    bool forceGlobal = 
     (task.Options & TaskCreationOptions.PreferFairness) != TaskCreationOptions.None; 
    ThreadPool.UnsafeQueueCustomWorkItem(task, forceGlobal); 
    } 
} 
+3

Tôi không thấy có gì sai với câu trả lời của mình. Bạn có thể giải thích những gì lý do của bạn là cho downvote? –

+3

@Ramhound Tôi nhận ra đây là cổ, nhưng xp! = Câu trả lời đúng. Alois là chính xác, hãy xem mã nguồn của .NET Framework cho 'ThreadPoolTaskScheduler' - phương thức thứ hai trong' QueueTask': referencesource.microsoft.com/#mscorlib/system/threading/Tasks/ThreadPoolTaskScheduler.cs Thậm chí có một chú thích trong mã: // Chạy các tác vụ LongRunning trên chuỗi chuyên dụng của riêng chúng. –

8

Tùy thuộc vào Trình lập lịch biểu bạn sử dụng. Có hai triển khai cổ phiếu, ThreadPoolTaskScheduler và SynchronizationContextTaskScheduler. Cái sau không bắt đầu một luồng nào cả, được sử dụng bởi phương thức FromCurrentSynchronizationContext().

ThreadPoolTaskScheduler là những gì bạn nhận được. Mà thực sự sử dụng tùy chọn LongRunning, nó sẽ sử dụng một Thread thường xuyên nếu nó được thiết lập. Quan trọng để tránh đói các chủ đề TP khác. Bạn sẽ nhận được một chủ đề TP mà không có tùy chọn. Đây là những chi tiết triển khai có thể thay đổi mà không cần thông báo, mặc dù tôi sẽ sớm xem xét nó sớm.

+0

Tại sao tôi không thể tìm thấy bất kỳ kết quả (bài viết MSDN trực tuyến) nào được tìm kiếm bởi trang 'ThreadPoolTaskScheduler: msdn.microsoft.com -site: social.msdn.microsoft.com' hoặc bởi trang 'SynchronizationContextTaskScheduler: msdn.microsoft.com -site: social .msdn.microsoft.com'? –

+1

Vì chúng là các lớp bên trong. Như tôi đã đề cập, "chi tiết triển khai". –

+0

Cảm ơn. Tôi có thể hỏi "triển khai cổ phiếu" là gì không? –