ich sowohl mit Marc und Stephen zustimmen (Cleary).
(BTW, begann ich dies als Kommentar zu Stephen's Antwort zu schreiben, aber es stellte sich heraus, zu lang zu sein; lassen Sie mich wissen, wenn es OK ist, dies als Antwort zu schreiben oder nicht, und fühlen Sie sich frei, Bits zu nehmen daraus und fügen Sie es Stephen's Antwort, im Geiste der "Bereitstellung der besten Antwort").
Es hängt wirklich "ab": wie Marc sagte, ist es wichtig zu wissen, wie DoSomethingAsync asynchron ist. Wir sind uns alle einig, dass es keinen Sinn macht, wenn die "sync" -Methode die "async" -Methode aufruft und "wartet": Dies kann im Benutzercode geschehen. Der einzige Vorteil einer separaten Methode besteht darin, tatsächliche Leistungsgewinne zu erzielen, eine Implementierung zu haben, die unter der Haube anders ist und auf das synchrone Szenario zugeschnitten ist. Dies trifft insbesondere zu, wenn die "async" -Methode einen Thread erstellt (oder aus einem threadpool): Sie haben am Ende etwas, das darunter zwei "Kontrollflüsse" verwendet, während "vielversprechend" mit seinen synchronen Looks in der ausgeführt wird Kontext der Anrufer. Dies kann je nach Implementierung sogar Nebenläufigkeitsprobleme haben.
Auch in anderen Fällen, wie die intensive I/O, die das OP erwähnt, kann es sich lohnen, zwei verschiedene Implementierungen zu haben.Die meisten Betriebssysteme (Windows für sicher) haben für I/O unterschiedliche Mechanismen, die auf die beiden Szenarien zugeschnitten sind: Async-Ausführung und I/O-Operation bringt große Vorteile von OS-Level-Mechanismen wie I/O-Completion-Ports Overhead (nicht signifikant, aber nicht null) im Kernel (schließlich müssen sie Buchhaltung, Versand, etc.) und direktere Implementierung für synchrone Operationen. Die Code-Komplexität variiert auch sehr, besonders bei Funktionen, bei denen mehrere Operationen ausgeführt/koordiniert werden.
Was ich tun würde, ist:
- haben einige Beispiele/Test für typische Verwendung und Szenarien
- sehen, welche API-Variante verwendet wird, wo und zu messen. Messen Sie auch den Leistungsunterschied zwischen einer "reinen Sync" -Variante und "Sync". (nicht für die gesamte API, sondern für ausgewählte wenige typische Fälle)
- basierend auf Messung, entscheiden, ob die zusätzlichen Kosten es wert ist.
Dies vor allem, weil zwei Ziele irgendwie im Gegensatz zueinander stehen. Wenn Sie wartbaren Code möchten, ist es naheliegend, die Synchronisation in async/wait (oder anders herum) zu implementieren (oder, noch besser, nur die async-Variante bereitzustellen und den Benutzer warten zu lassen); Wenn Sie Leistung wünschen, sollten Sie die beiden Funktionen unterschiedlich implementieren, um verschiedene zugrunde liegende Mechanismen (vom Framework oder vom Betriebssystem) auszunutzen. Ich denke, dass es aus Sicht des Komponententests keinen Unterschied machen sollte, wie Sie Ihre API tatsächlich implementieren.
Wichtige Frage: Wie ist der Async-Teil von 'DoSomethingAsync' implementiert? Dies ist wichtig, denn wenn Sie einen "Task" und einen Worker-Thread erstellen, kann die Antwort sehr unterschiedlich sein, wenn Sie beispielsweise eine externe Event-API verwenden. Insbesondere hat es keinen Sinn, wenn die "sync" -Methode die "async" -Methode und "wait" aufruft, wenn die "async" -Methode einen Thread verwendet: Es wäre besser, die Arbeit direkt zu machen. Dies ändert sich jedoch für andere Bedeutungen von "async" (nicht alle "async" bedeutet "Threads") –
@MarcGravell, versuche ich besser zu erklären (und es ist nicht einfach, weil Englisch nicht meine primäre Sprache ist). Ich habe "Operation XYZ", die intensive I/O machen. Ich möchte es in einer Bibliothek mit zwei Methoden verfügbar machen: eine, die fast sofort mit einem asynchronen Muster zurückkehrt (wie beschrieben in _MS taskbasiertes asynchrones Muster doc_) und eines, das synchron ausführt. Was ist der ** effizient **/** wartbare **/** Unit-Test aktiviert ** Weg dazu. Eine private Methode, die mit einem öffentlichen Async-Wrapper und einem anderen Sync-Wrapper, z. Wenn ja, wie sehen diese Methoden aus? – jay
"Effizient" und "Wartungsfähig" sind nicht dasselbe und stimmen oft nicht überein. Und noch einmal: Alles hängt davon ab, wie Ihr "Async" -Code derzeit funktioniert. Wenn das prozeduraler/linearer Code ist, den Sie gerade in einem separaten Thread ausführen, dann gibt es keinen Grund, ihn über "async" offenzulegen. Wenn dieser Code vollständig asynchron ist, ist es möglicherweise am besten, zwei vollständig getrennte Implementierungen zu verwenden, wenn Sie "effizient" als Ziel haben möchten. Entschuldigung, aber diese Frage ist ** sehr kontextspezifisch und du hast nicht viel Kontext angegeben. –