Asynchrone Aufgabe in asp .net MVC 5
Ich bin versucht, async, await und der task zu implementieren eine asynchrone Anforderung, die in meiner web-Anwendung. Ich habe folgenden code in meiner controller-Klasse. Was ich möchte ist, dass, nachdem die Strömung erreicht zu drucken "controller 1", startet das system die business-Methode in einem separaten thread und ohne warten auf die Antwort-system erreichen sollte, um print-Anweisung im controller und print "controller 2". Aber wenn ich die ausführen den folgenden code, erhalte ich die Ausgabe Muster als
controller 1
PlandesignBS
controller 2
Während ich erwarte dies-
controller 1
controller 2 (Flow should reach here immediately rather than waiting
for business methods to get executed First)
Controller-Klasse Code-
public class PlanDetailsController : Controller
{
[HttpPost]
public async Task<ActionResult> Generate(PlanDetailsVM planDetailsVM)
{
System.Diagnostics.Debug.WriteLine("controller 1");
//calls business method to generate
quoteId = await Task.Run(() => _planDesignBS.GenerateBS(planDetailsVM));
System.Diagnostics.Debug.WriteLine("controller 2");
return Json(quoteId , JsonRequestBehavior.AllowGet);
}
}
Business-Methode, Code-
public int GenerateBS(PandetailsDTO plandetails)
{
System.Diagnostics.Debug.WriteLine("PlandesignBS");
//STEP 1-> call to dataLogic Layer to use Entity Framework
//STEP 2-> call to a method (this method is part of dll used
//in our project and we don't have any control on it)
return quoteId
}
EDIT: Der Grund, warum ich versuche, dies zu tun ist, dass ich verwenden möchten, einige http-Posts-Anfragen von meinem client-Seite. Angenommen, ich nenne das Erzeugen action-Methode zuerst von meinem client-Seite und dann nicht wollen, zu warten, für die Reaktion von ihm und zur gleichen Zeit wollen ein anderes aufrufen von http post.
EDIT: Einschließlich der EF-code, wo ich bin immer execption, wenn ich versuche zu Folgen, nur wenige Lösungen.Diese Methode wird aufgerufen, aus meiner GenerateBS Methode. Ich bin immer die Ausnahme auf dieser Linie innerhalb getSICCode Methode-
DbContext.Database.ExecuteSqlCommand("spGET_SICCode @industryClasifID,@industrySubClasifID,@SICCode OUTPUT", industryClasifID, industrySubClasifID, SICCode);
EF Code-
public class PlanDesignRepository : Repository<myobject>, IPlanDesignRepository
{
private IDbSet<myobject> _dbSet;
private DbContext _dbContext;
private IDbSet<myobject> DbSet
{
get
{
if (_dbSet == null)
{
_dbSet = base.UnitOfWork.Context.Set<myobject>();
}
return _dbSet;
}
}
private DbContext DbContext
{
get
{
if (_dbContext == null)
{
_dbContext = base.UnitOfWork.Context;
}
return _dbContext;
}
}
public string GetSICCode(IndustryClassficDO industryClassficDO)
{
SqlParameter industryClasifID = new SqlParameter("industryClasifID", SqlDbType.Int);
industryClasifID.Value = industryClassficDO.IndustryClassificationId;
SqlParameter industrySubClasifID = new SqlParameter("industrySubClasifID", SqlDbType.Int);
industrySubClasifID.Value = industryClassficDO.IndustrySubClassificationId;
SqlParameter SICCode = new SqlParameter("SICCode", SqlDbType.VarChar, 10);
SICCode.Direction = ParameterDirection.Output;
DbContext.Database.ExecuteSqlCommand("spGET_SICCode @industryClasifID,@industrySubClasifID,@SICCode OUTPUT", industryClasifID, industrySubClasifID, SICCode);
return (string)(SICCode.Value);
}
}
EDIT: ich habe einige http-Post-Aufrufe, wie unten gezeigt-
AngularJS code for AJAX calls:
$http({
url: key_Url_Generate,
method: Post,
params: $scope.PlanDetails
}).then(function (result) {
//Notify user for success or failure
}
- Wie wollen Sie Sie Entsorgen DataContext?
- Was sollte ich tun, um es Entsorgen?
- Sollten Sie die Dispose-Methode aufrufen, aber ich bin nicht sage Ihnen, es Entsorgen bin ich Fragen, wo Sie es Entsorgen, weil die Ausnahme, die Sie Bericht sagt, dass die Dispose-Methode aufgerufen wurde, aber einige Codes versucht, das Objekt zu verwenden, dass nach.
- Ich bin nicht vertraut mit den eckigen, aber das sieht aus wie eine einzige Anfrage. Wenn Sie zwei separate $http(...) fordert, Sie sollen gleichzeitig gesendet werden. Stellen Sie sicher, dass Sie nicht zu fügen Sie den zweiten Anruf Rückruf (dann-Funktion)
- ja, aber ich weiß nicht, warum ist es nicht für mich arbeiten. Ich werde versuchen, was löst meine Frage, ob die code-änderung in der client-seitige code-oder der server-Seite code.
- Die server-Seite zu ändern wird nicht das Problem lösen. Wo ist der code für die zweite AJAX-Anfrage?
- Es ist ähnlich wie diese...einzige Unterschied ist die url, die zeigen, um verschiedene action-Methode des Controllers.
- Wie hast du den zweiten Antrag ist zu warten, für den ersten? Tun, die browser-tools zeigen die zweite Anfrage nicht erteilt werden, bevor die erste abgeschlossen ist? Sie haben alles, was blockiert Sie den code wie eine Warnung?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Verwendung von await bedeutet, dass Sie warten, für die Aufgabe abzuschließen, bevor Sie den code. Wenn Sie möchten, es zu führen und gleichzeitig mit der anderen code, den Sie ändern sollte es so
Aber ich würde nicht empfehlen, es dient keinem Zweck und die Leistung beeinträchtigen kann, über die hungernden ASP.NET thread-pool-threads. Warum willst du das überhaupt?
Diese Zeile:
einesynchron wartet für den Aufruf innerhalb
Task.Run
zu vervollständigen. Das ist, warum Sie"PlandesignBS"
gedruckt und erst danach sehen Sie den Aufruf von controller 2.Wenn Sie wollen, ein "fire-and-forget" - Stil der Ausführung, die Sie tatsächlich nicht wollen gewartet.
Sollten Sie auf jeden Fall nicht verwenden
Task.Run
innen ASP.NET an alle, als es gefährlich. Stattdessen, wenn Sie auf .NET 4.5.2 und oben, können SieHostingEnvironment.QueueBackgroundWorkItem
oder wenn nicht, können SieBackgroundTaskManager
von Stephan Cleary, die Sie sicher Register der hintergrund-thread mit den Anwendungspool, damit dein thread nicht beendet, wenn eine re-cycle aufgerufen:Als seitliche Anmerkung - Wenn Sie anrufen Entity Framework, es gibt in der Regel keine Notwendigkeit der Beteiligung von extra-threads. Version 6 und höher verfügbar macht TIPPEN Sie auf async-basiertes API ' s die
Task
zurückgeben, die Sie verwenden können, zu Ihrer Verfügung, für diese Art von IO-basierten Abfragen.IRegisteredObject
- Schnittstelle. Hier ist ein einfacher Spaziergang durch die können Sie loslegen. Auch Sie können sich an der Umsetzung derBackgroundTaskManager
Das problem ist,, dass Sie einfach nicht Versand asynchroner code, fallen aus dem asp.net Anfrage-pipeline per se.
Den async-feature asp.net MVC nur eine Verbesserung der internen Handhabung von threads innerhalb des IIS-Prozesses. Es ermöglicht es NICHT, Sie zu beenden, und schließen Sie die Antwort an den client, bevor die Ausführung abgeschlossen ist.
Wenn Sie möchten, eine echte "fire-and-forget" Lösung, Sie brauchen mehr als das.
Kurzem hatte ich die Anforderung, dass mails gesendet werden, asynchron, nachdem ein Formular in eine web-Anwendung senden.
Die einzige Möglichkeit, die ich gefunden, um dieses problem zu lösen, war der Einsatz von
hangfire
:http://hangfire.io/
Versuchen Sie dies: