27 votes

Différence entre delegate.BeginInvoke et l'utilisation de threads ThreadPool en C #

En C #, y a-t-il une différence entre l'utilisation d'un délégué pour effectuer un travail de manière asynchrone (appel de BeginInvoke ()) et l'utilisation d'un thread ThreadPool comme indiqué ci-dessous

 public void asynchronousWork(object num)
    {
        //asynchronous work to be done
        Console.WriteLine(num);
    }

 public void test()
    {
        Action<object> myCustomDelegate = this.asynchronousWork;
        int x = 7;

        //Using Delegate
        myCustomDelegate.BeginInvoke(7, null, null);

        //Using Threadpool
        ThreadPool.QueueUserWorkItem(new WaitCallback(asynchronousWork), 7);
        Thread.Sleep(2000);
    }
 

Éditer:
BeginInvoke s'assure qu'un thread du pool de threads est utilisé pour exécuter le code asynchrone, donc y a-t-il une différence?

30voto

Lee Points 63849

Joe Duffy, dans son Concurrent Programming on Windows livre (page 418), dit ceci à propos de Delegate.BeginInvoke:

Tous les types délégués, par convention offre un BeginInvoke et EndInvoke méthode côtés de l'ordinaire synchrone Invoke méthode. Alors que c'est un joli modèle de programmation fonctionnalité, vous devriez rester loin d'eux si possible. La mise en œuvre utilise remoting infrastructure qui impose une importante surcharge invocation asynchrone. La file d'attente de travail pour le pool de threads directement est souvent une meilleure approche, même si cela signifie que vous devez coordonner les rendez-vous de la logique de vous-même.

EDIT: j'ai créé le simple test de la relative frais généraux:

int counter = 0;
int iterations = 1000000;
Action d = () => { Interlocked.Increment(ref counter); };

var stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
for (int i = 0; i < iterations; i++)
{
    var asyncResult = d.BeginInvoke(null, null);
}

do { } while(counter < iterations);
stopwatch.Stop();

Console.WriteLine("Took {0}ms", stopwatch.ElapsedMilliseconds);
Console.ReadLine();

Sur ma machine le test ci-dessus s'exécute en environ 20 secondes. Le remplacement de l' BeginInvoke d'appels avec

System.Threading.ThreadPool.QueueUserWorkItem(state =>
{
    Interlocked.Increment(ref counter);
});

les modifications de la durée de fonctionnement de 864ms.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X