5

Tôi sẽ phải tạo một phần mềm đồng thời tạo nhiều nhiệm vụ và mỗi tác vụ có thể tạo ra một nhiệm vụ khác. .).Làm thế nào để chờ đợi trên tất cả các tác vụ (tạo nhiệm vụ và nhiệm vụ phụ) mà không sử dụng TaskCreationOptions.AttachedToParent

Tôi cần cuộc gọi đến phương thức khởi chạy tác vụ đang chặn: không trả về TRƯỚC KHI tất cả nhiệm vụ và nhiệm vụ phụ được hoàn thành.

Tôi biết có là tài sản TaskCreationOptions.AttachedToParent này, nhưng tôi nghĩ rằng nó sẽ không phù hợp:

Các máy chủ sẽ có một cái gì đó giống như 8 lõi ít ​​nhất, và mỗi công việc sẽ tạo ra 2-3 công việc phụ, vì vậy nếu tôi đặt AttachedToParent tùy chọn, tôi đã ấn tượng rằng nhiệm vụ phụ thứ hai sẽ không bắt đầu trước khi ba nhiệm vụ của subtask đầu tiên kết thúc. Vì vậy, tôi sẽ có một đa nhiệm hạn chế ở đây.

Vì vậy, với cây quá trình này:

enter image description here

Tôi đã ấn tượng rằng nếu tôi đặt AttachedToParent mọi tài sản tôi khởi động một thread, B sẽ không kết thúc trước E, F, G đã kết thúc, vì vậy C sẽ bắt đầu trước khi B kết thúc, và tôi sẽ chỉ có 3 hoạt động chủ đề thay vì 8 tôi có thể có.

Nếu tôi không đặt thuộc tính AttachedToParent, A sẽ được hoàn thành rất nhanh và trả về.

Vậy làm cách nào tôi có thể thực hiện để đảm bảo rằng tôi luôn sử dụng 8 lõi nếu tôi không đặt tùy chọn này?

+3

Đừng dựa vào ấn tượng. Hoặc tìm trong tài liệu hoặc tự mình thử. – svick

Trả lời

2

TaskCreationOptions.AttachedToParent không ngăn các nhiệm vụ phụ khác bắt đầu, mà đúng hơn là ngăn không cho tác vụ gốc tự đóng. Vì vậy, khi E, F và G được bắt đầu với AttachedToParent, B không được gắn cờ là xong cho đến khi cả ba kết thúc. Vì vậy, nó nên làm như bạn muốn.

source (trong câu trả lời được chấp nhận).

2

Như tôi. Đã đề cập, AttachedToParent không hoạt động theo số lần hiển thị của bạn. Tôi nghĩ rằng đó là một lựa chọn tốt trong trường hợp này.

Nhưng nếu bạn không muốn sử dụng điều đó vì bất kỳ lý do gì, bạn có thể đợi tất cả các nhiệm vụ con để hoàn thành với Task.WaitAll(). Mặc dù nó có nghĩa là bạn phải có tất cả chúng trong một bộ sưu tập.

Task.WaitAll() chặn luồng hiện tại cho đến khi tất cả các Task s được hoàn tất. Nếu bạn không muốn điều đó và bạn đang ở trên .Net 4.5, bạn có thể sử dụng Task.WhenAll(), sẽ trả về một Task duy nhất sẽ kết thúc khi tất cả các kết thúc được cung cấp Task s.

1

Bạn có thể giúp bạn TaskFactory tạo các tùy chọn như trong ví dụ này:

Task parent = new Task(() => { 
var cts = new CancellationTokenSource(); 
var tf = new TaskFactory<Int32>(cts.Token, 
             TaskCreationOptions.AttachedToParent, 
             TaskContinuationOptions.ExecuteSynchronously, 
TaskScheduler.Default); 

// This tasks creates and starts 3 child tasks 
var childTasks = new[] { 
     tf.StartNew(() => Sum(cts.Token, 10000)), 
     tf.StartNew(() => Sum(cts.Token, 20000)), 
     tf.StartNew(() => Sum(cts.Token, Int32.MaxValue)) // Too big, throws Overflow 
}; 

// If any of the child tasks throw, cancel the rest of them 
for (Int32 task = 0; task <childTasks.Length; task++) 
    childTasks[task].ContinueWith( 
    t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted); 

// When all children are done, get the maximum value returned from the 
// non-faulting/canceled tasks. Then pass the maximum value to another 
// task which displays the maximum result 
tf.ContinueWhenAll( 
    childTasks, 
    completedTasks => completedTasks.Where( 
    t => !t.IsFaulted && !t.IsCanceled).Max(t => t.Result), CancellationToken.None) 
    .ContinueWith(t =>Console.WriteLine("The maximum is: " + t.Result), 
     TaskContinuationOptions.ExecuteSynchronously); 
}); 

// When the children are done, show any unhandled exceptions too 
parent.ContinueWith(p => { 
    // I put all this text in a StringBuilder and call Console.WriteLine just once 
    // because this task could execute concurrently with the task above & I don't 
    // want the tasks' output interspersed 
    StringBuildersb = new StringBuilder( 
         "The following exception(s) occurred:" + Environment.NewLine); 

    foreach (var e in p.Exception.Flatten().InnerExceptions) 
     sb.AppendLine(" "+ e.GetType().ToString()); 

    Console.WriteLine(sb.ToString()); 
    }, TaskContinuationOptions.OnlyOnFaulted); 

    // Start the parent Task so it can start its children 
    parent.Start(); 
Các vấn đề liên quan