c# - world - create rest api dotnet core




Verwendung von async/await oder task im Web-Api-Controller(.net core) (2)

Ich habe eine .net-Kern-API, die über einen Controller verfügt, der ein aggregiertes Objekt zum Zurückgeben erstellt. Das Objekt, das es erstellt, besteht aus Daten, die aus 3 Methodenaufrufen an eine Serviceklasse stammen. Diese sind alle unabhängig voneinander und können isoliert voneinander betrieben werden. Derzeit verwende ich Aufgaben, um die Leistung dieses Controllers zu verbessern. Die aktuelle Version sieht ungefähr so ​​aus ...

[HttpGet]
public IActionResult myControllerAction()
{      
    var data1 = new sometype1();
    var data2 = new sometype2();
    var data3 = new List<sometype3>();

    var t1 = new Task(() => { data1 = service.getdata1(); });
    t1.Start();

    var t2 = new Task(() => { data2 = service.getdata2(); });
    t2.Start();

    var t3 = new Task(() => { data3 = service.getdata2(); });
    t3.Start();

    Task.WaitAll(t1, t2, t3);

    var data = new returnObject
    {
         d1 = data1,
         d2 = data2,
         d2 = data3
    };

    return Ok(data);
}

Das funktioniert gut, aber ich frage mich, ob die Verwendung von Aufgaben die beste Lösung ist? Würde async / erwarten eine bessere Idee und mehr akzeptiert werden?

Zum Beispiel sollte der Controller als async markiert werden und auf jeden Aufruf der Service-Methoden gewartet werden?


Das funktioniert gut, aber ich frage mich, ob die Verwendung von Aufgaben die beste Lösung ist? Würde async / erwarten eine bessere Idee und mehr akzeptiert werden?

Ja absolut. Bei der parallelen Verarbeitung von ASP.NET werden mehrere Threads pro Anforderung verwendet, was sich erheblich auf die Skalierbarkeit auswirken kann. Asynchrone Verarbeitung ist für E / A weit überlegen.

Um async , starten Sie zuerst mit Ihrem Anruf auf der untersten Ebene, irgendwo in Ihrem Dienst. Wahrscheinlich führt es irgendwann einen HTTP-Aufruf durch; Ändern Sie dies, um asynchrone HTTP-Aufrufe zu verwenden (z. B. HttpClient ). Lassen Sie dann async natürlich von dort wachsen.

Schließlich erhalten Sie die asynchronen Methoden getdata1Async , getdata2Async und getdata3Async , die gleichzeitig als solche verwendet werden können:

[HttpGet]
public async Task<IActionResult> myControllerAction()
{
  var t1 = service.getdata1Async();
  var t2 = service.getdata2Async();
  var t3 = service.getdata3Async();
  await Task.WhenAll(t1, t2, t3);

  var data = new returnObject
  {
    d1 = await t1,
    d2 = await t2,
    d3 = await t3
  };

  return Ok(data);
}

Bei dieser Vorgehensweise verwendet myControllerAction während der drei Serviceaufrufe null Threads anstelle von vier Threads.


Wie ich es verstehe, möchten Sie, dass dies parallel ausgeführt wird, also glaube ich nicht, dass mit Ihrem Code etwas nicht stimmt. Wie Gabriel erwähnte, könntest du auf den Abschluss der Aufgaben warten.

[HttpGet]
public async IActionResult myControllerAction()
{      
  var data1 = new sometype1();
  var data2 = new sometype2();
  var data3 = new List<sometype3>();

  var t1 = Task.Run(() => { data1 = service.getdata1(); });
  var t2 = Task.Run(() => { data2 = service.getdata2(); });
  var t3 = Task.Run(() => { data3 = service.getdata3(); });

  await Task.WhenAll(t1, t2, t3); // otherwise a thread will be blocked here

  var data = new returnObject
  {
      d1 = data1,
      d2 = data2,
      d2 = data3
  };

 return Ok(data);
}

Sie können auch die Ergebnisse der Aufgaben verwenden, um einige Codezeilen zu speichern und den Code insgesamt "besser" zu machen (siehe Kommentare):

[HttpGet]
public async IActionResult myControllerAction()
{      
  var t1 = Task.Run(() => service.getdata1() );
  var t2 = Task.Run(() => service.getdata2() );
  var t3 = Task.Run(() => service.getdata3() );

  await Task.WhenAll(t1, t2, t3); // otherwise a thread will be blocked here

  var data = new returnObject
  {
      d1 = t1.Result,
      d2 = t2.Result,
      d2 = t3.Result
  };

 return Ok(data);
}




asp.net-core