Mam problem ze zrozumieniem, jak działa parametr AttachedToParent
.AttachedToParent Zadanie pomyłki
Oto przykładowy kod:
public static void Main(string[] args)
{
Task<int[]> parentTask = Task.Run(()=>
{
int[] results = new int[3];
Task t1 = new Task(() => { Thread.Sleep(3000); results[0] = 0; }, TaskCreationOptions.AttachedToParent);
Task t2 = new Task(() => { Thread.Sleep(3000); results[1] = 1; }, TaskCreationOptions.AttachedToParent);
Task t3 = new Task(() => { Thread.Sleep(3000); results[2] = 2; }, TaskCreationOptions.AttachedToParent);
t1.Start();
t2.Start();
t3.Start();
return results;
});
Task finalTask = parentTask.ContinueWith(parent =>
{
foreach (int result in parent.Result)
{
Console.WriteLine(result);
}
});
finalTask.Wait();
Console.ReadLine();
}
Jak rozumiem, gdy zadanie ma Zadania dziecko, rodzic Zadanie kończy się, gdy wszystkie zadania podrzędne są gotowe. Problem z tym przykładem jest taki, że wyjście wygląda następująco:
0
0
0
Oznacza to, że zadanie nadrzędne nie czekało na zakończenie zadań podrzędnych. Jedynym sposobem, aby uzyskać poprawny wynik 0 1 2
jest użycie Poczekaj na wszystkie dzieci taks, dodając jakiś kawałek kodu jak ten przed stwierdzeniem return results;
:
Task[] taskList = { t1, t2, t3 };
Task.WaitAll(taskList);
Moje pytanie jest takie. Dlaczego używamy TaskCreationOptions.AttachedToParent
, kiedy musimy ręcznie wywoływać metodę Wait dla każdego dziecka Zadanie?
Edit:
Chociaż pisałem to pytanie, mam zmieniony kod trochę i teraz AttachedToParent działa dobrze. Jedyna różnica polega na tym, że użyłem parentTask.Start();
zamiast Task.Run();
.
public static void Main(string[] args)
{
Task<int[]> parentTask = new Task<int[]>(()=>
{
int[] results = new int[3];
Task t1 = new Task(() => { Thread.Sleep(3000); results[0] = 0; }, TaskCreationOptions.AttachedToParent);
Task t2 = new Task(() => { Thread.Sleep(3000); results[1] = 1; }, TaskCreationOptions.AttachedToParent);
Task t3 = new Task(() => { Thread.Sleep(3000); results[2] = 2; }, TaskCreationOptions.AttachedToParent);
t1.Start();
t2.Start();
t3.Start();
//Task[] taskList = { t1, t2, t3 };
//Task.WaitAll(taskList);
return results;
});
parentTask.Start();
Task finalTask = parentTask.ContinueWith(parent =>
{
foreach (int result in parent.Result)
{
Console.WriteLine(result);
}
});
finalTask.Wait();
Console.ReadLine();
}
Nadal nie rozumiem, dlaczego występuje problem z pierwszym przykładem.
* DenyChildAttach * wydaje się być problemem. Kiedy tworzę zadanie nadrzędne w następujący sposób: 'TaskFactory tf = new TaskFactory (TaskCreationOptions.DenyChildAttach, TaskContinuationOptions.None); Zadanie parentTask = tf.StartNew (() => {....}); 'Otrzymuję ten sam problem i kiedy używam * TaskCreationOptions.None * działa dobrze. –