De la tâche.WaitAll() ne fonctionne pas comme prévu

Je suis à essayer de comprendre comment travailler avec le groupe classe. Dans le passé, j'ai toujours utilisé le régulier de la classe Thread, mais j'essaie de saisir l'ensemble de la programmation asynchrone...

Comme un exemple, j'ai créé l'un des principaux Winforms application qui dispose de tous le code.
Le code pour mon problème est:

//Relevant delegates
public delegate void MethodAction(int num);
public delegate void MethodConversion();
public delegate void OnCompletionAction(string completiontext);

//Button user presses
private void button4_Click(object sender, EventArgs e)
{
    richTextBox1.Clear();
    sw.Reset();
    sw.Start();
    Sync.RunAsync3(calcSim);
}

//The method that simulates a calculation by adding a sleep
//the input param threadlength is just to allow threads to take longer than others
//since I'm multithreading, I have to invoke the writing code on the windows RichTextbox control
private void calcSim(int threadlength)
{
    string threadname = Thread.CurrentThread.Name;
    for (int i = 0; i < 10; i++) //Thread calc should take 3s
    {
        Thread.Sleep(300 + threadlength);
        richTextBox1.Invoke((MethodConversion)(() =>
                            { 
                                richTextBox1.AppendText(string.Format("Thread: {0}\tVersion: {1}\n", threadname, (i + 1).ToString())); 
                            }));
    }
}

//Class that contains the different processing methods
public static class Sync
{
    public static event OnCompletionAction OnProcCompletion;

    public static void RunAsync3(MethodAction doM)
    {
        Task[] t = new Task[4];
        for(int i = 0; i < 4; i++)
        {
            t[i] = Task.Factory.StartNew((Action)(() => { doM(50 * i); }));
        }
        Task.WaitAll(t);
        if (OnProcCompletion != null) OnProcCompletion("RunSync method finished");
    }
}

Le problème réside dans la Tâche.WaitAll(t)... Pour une raison que je ne peux pas comprendre, elle bloque complètement sur cette ligne et ne répond plus. Si je omettre la ligne, la forme est mise à jour en temps réel et l'exécution dure environ 3 secondes.

Ma question est: pourquoi n'est-ce pas la Tâche.WaitAll() bloque le thread d'INTERFACE utilisateur pour 3 secondes avant de le relâcher et permettant le reste du code à exécuter?

Je sais que ça doit être le blocage de l'INTERFACE utilisateur pour un certain temps (jusqu'à ce que tous les threads de calcul), mais elle bloque la complète des applications à l'infini. Il semble être en attente pour toujours?

MODIFIER

J'ai été suggéré d'utiliser WhenAll au lieu de WaitAll. J'ai réécrit RunAsync3 comme suit:

public static void RunAsync3(MethodAction doM)
{
    Task[] t = new Task[4];
    for(int i = 0; i < 4; i++)
    {
        t[i] = Task.Factory.StartNew((Action)(() => { doM(50 * i); }));
    }
    //Task.WaitAll(t); -> deadlock
    Task.WaitAll(new Task [] { Task.WhenAll(t) });
    if (OnProcCompletion != null) OnProcCompletion("RunSync method finished");
}

Mais c'est toujours dans l'impasse...? Je suis peut-être à l'aide de la WhenAll mal?

EDIT 2

Parce que tout le monde en déclarant que j'étais bloquer le thread de l'INTERFACE utilisateur ont été à droite, j'ai décidé d'essayer cette autre manière: en cours d'exécution d'un thread que mon thread appelant à l'intérieur de la thread d'INTERFACE utilisateur (de sorte que le blocage de maintenant se ferait sur mon thread au lieu de thread d'INTERFACE utilisateur). Cela fonctionne, mais n'est évidemment pas la meilleure façon de le faire!

private void button4_Click(object sender, EventArgs e)
{
    Thread t = new Thread(new ThreadStart(() =>
    {
        richTextBox1.Invoke((MethodConversion)(() => richTextBox1.Clear()));
        sw.Reset();
        sw.Start();
        Sync.RunAsync3(calcSim);
    }));
    t.Start();
}
public static void RunAsync3(MethodAction doM)
{
    Task[] t = new Task[4];
    for(int i = 0; i < 4; i++)
    {
        t[i] = Task.Factory.StartNew((Action)(() => { doM(50 * i); }));
    }
    Task.WaitAll(t);
   //Task.WaitAll(new Task [] { Task.WhenAll(t) });
   if (OnProcCompletion != null) OnProcCompletion("RunSync method finished");
}
En Raison De La Tâche.WaitAll(t); s'exécute dans le thread de l'INTERFACE utilisateur!
Je sais que ça doit bloquer le thread d'INTERFACE utilisateur, qui n'est pas le problème. Le problème est qu'il n'a jamais continue avec le reste du code. Il semble que c'est l'attente interminable!
Puisque vous essayez de "Invoquer" quelque chose sur le thread principal qui est dans un waitstate, à partir d'un travailleur?
Vous devriez envisager de await Task.WhenAll(...);
Une alternative serait de pousser les actions que vous faites sur une pile, et après la waitall (qui sera alors le travail puisque vous n'êtes pas d'essayer d'appeler le thread principal est plus pop & exécuter la construction de la pile

OriginalL'auteur Recipe | 2013-11-04