/ / Asynch-Aufrufe versus Multithreading - .net, asynchrone Windows-Dienste

Asynch-Aufrufe versus Multi-Threading - .net, asynchrone, Windows-Dienste

Ich habe einen Windows-Dienst in VB.NET, das nacheinander mehrere lange laufende Prozesse aufruft (normale Subroutinen, kein Web-SVC, Remoting oder ähnliches). Ich bin müde zu versuchen, Multithreading zu implementieren, nur weil wir es noch nie zuvor gemacht haben und dies ein missionskritischer Code ist. Ich hatte den Gedanken, die Routinen stattdessen asynchron aufzurufen. Ich bin damit vertraut und benutze es als Teil einiger Webdienste. Fehlt mir etwas? Asynchrone Anrufe scheinen eine "Poor Mans" -Methode zu sein, um Multithreading-Probleme zu vermeiden.

Antworten:

1 für die Antwort № 1

Asynchrone Aufrufe sind in der Regel besser als reguläres Multithreading, da sie den im Hinblick auf die CPU-Auslastung effizienteren Thread für E / A-Vervollständigungsports nutzen.


1 für die Antwort № 2

Asynchrone Aufrufe scheinen ein "Poor Mans" zu sein, um Multithreading-Probleme zu vermeiden.

Nicht unbedingt. Javascript (und Servervarianten von Javascript wie Node.js) werden auf einem einzelnen Thread ausgeführt, verwenden jedoch viel Asynchronität, sodass nicht viel Zeit darauf verwendet wird, auf einen langen laufenden Vorgang zu warten. Es ist eine Methode zur Optimierung eines einzelnen Threads und kann eine sehr leistungsfähige Methode zur Programmierung sein, wenn Sie die richtige Einstellung haben.

Wenn Sie mit asynchroner Programmierung vertraut sind, sollten Sie es versuchen. Es ist nicht erforderlich, eine ganze Reihe von Threads einzubringen, nur weil eine Task parallelisiert werden kann.

Wenn die Aufgaben jedoch an die CPU gebunden sind, wird ein einzelner Thread ersticken und die Asynchronität wird Ihnen aus offensichtlichen Gründen nicht helfen. Wenn die Aufgabe E / A ist, ist die Asynchronität wahrscheinlich der richtige Weg.

Bearbeiten:

Es tut mir leid, dass ich nicht klar war. Was ich unter CPU-gebunden verstehe, ist, dass der Thread ständig verwendet wird und nicht für andere Aufgaben verfügbar ist, wenn eine bestimmte Operation viel CPU verwendet.

Beispielsweise:

// task
long sum = 0;
for (int i = 0; i < 1000000; i++)
for (int j = 1000000; j > 0; j--)
sum = i + j;

Wenn Sie den obigen Code zweimal ausführen mussten, wird einEin asynchrones Modell mit einem Thread hilft nicht weiter, da ein einzelner Thread für die gesamte Aufgabe ständig funktioniert. Wenn Sie zwei Threads hatten, können beide genau zur gleichen Zeit ausgeführt werden.

// task
List<string> urls = GetListOfUrls();
List<string> html = new List<string>();
foreach (var url in urls)
{
GetUrlAsync(url, callback: (data) => html.Add(data) );
}

Die obige Task ist eine E / A-Task. Die meiste Zeit in dieser Methode würde damit verbracht, auf HTTP-Anforderungen zu warten, ohne die CPU zu verwenden. Wenn diese Aufgabe synchron war, weist ein einzelner Thread dieselben Symptome wie der erste auf. Wenn es asynchron war und auf den Abschluss einer HTTP-Anforderung gewartet wurde, kann der Thread weitere Aufgaben ausführen, z. B. einen weiteren Download einer URL starten.

Verwenden Sie die Asynchronität, wenn Ihre Aufgaben viel Zeit darauf verwenden, auf einen externen Prozess zu warten. Verwenden Sie mehrere Threads, wenn Aufgaben CPU brennen sollen.


1 für die Antwort № 3

Ich weiß nicht, welche Multithreading-Probleme Sie durch asynchrone Aufrufe vermeiden sollten. Asynchrone Aufrufe sind Multithreading. Der einzige wirkliche Unterschied besteht darin, dass ein asynchroner Aufruf normalerweise für eine relativ kurzlebige Aufgabe verwendet wird, wohingegen herkömmliches Multithreading (bei dem Sie explizit einen Thread erstellen und ihn ausführen) normalerweise für Aufgaben mit langer Laufzeit verwendet wird.

In beiden Fällen haben Sie immer noch dieselben Probleme mit der Parallelität.

Sie kann Verwenden Sie asynchrone Aufrufe für Aufgaben mit langer Laufzeit. In der Tat, die Task Klasse hat einen Konstruktor, mit dem Sie angeben können Erstellungsoptionen, einschließlich TaskCreationOptions.LongRunning.

Verwalten Sie Ihre eigenen Threads mit der Thread Klasse ist ein bisschen komplizierter als mit etwas wie Task oder ThreadPool.QueueUserWorkItem, aber es gibt Ihnen auch etwas mehr Kontrolle. Wie auch immer Sie es tun, Sie müssen sich mit Parallelitätsproblemen wie Race-Bedingungen und thread-sicheren Datenstrukturen befassen (wenn mehrere Threads eine Datenstruktur ändern). Ich würde nicht asynchrone Anrufe als Multithreading eines "armen Mannes" bezeichnen. Die Unterschiede sind nicht so groß. Sie sind nur zwei verschiedene Wege, um dasselbe Ziel zu erreichen.