Wenn ich von IIS eine Hintergrundaufgabe in einem neuen Thread aufruft, wird es nur ausgeführt, wenn die Task bestimmte asynchrone Aufrufe nicht enthält.Thread-Abbruch-Ausnahme in .NET 4.5
Wenn ich eine Hintergrundaufgabe in einem neuen Thread aufrufen, die diese asynchrone Aufrufe enthält, ist es eine ThreadAbortException
zurückkehren, während die gleiche Aktion, innerhalb ApiController
synchron ausgeführt wird, wird durchlaufen, und eine andere Aktion, genannt asynchron läuft auch durch.
Darüber hinaus, wenn ich eine Aktion synchron sowie die andere Aktion asynchron aufrufen, schlägt der asynchrone Aufruf ebenfalls fehl.
- Was verursacht die
ThreadAbortException
? - Gibt es etwas, was ich tun kann, um die
ThreadAbortException
zu umgehen?
Code:
[HttpGet]
public string TestThreadAbortException()
{
InitToolkit(); // Initialize Logger, DB etc.
DebugController.DoAfter(5.Seconds(), MyAction); // Runs through!
//TestThreadAbortException(logger); // Runs through!
//Combining the first and the second line makes the first one throw the Exception as well.
//DebugController.DoAfter(10.Seconds(), TestThreadAbortException); // throws Exception
return String.Join("\r\n",logger.Flush());
}
private void TestThreadAbortException(Logger logger)
{
Task<string> task = new Task<string>(MyMethod);
task.Start();
Task.Run(async() => await task);
try
{
var result = ConfigureAwait(task, false).Result;
}
catch (System.AggregateException ex)
{
if (ex.InnerExceptions.Count == 1)
{
throw ex.InnerExceptions[0];
}
throw;
}
}
private async Task<string> ConfigureAwait(Task<string> task, bool continueOnCapturedContext)
{
return await task.ConfigureAwait(continueOnCapturedContext: continueOnCapturedContext);
}
private string MyMethod()
{
Thread.Sleep(20000);
return "Test";
}
private void MyAction(Logger logger)
{
logger.Log(MyMethod());
}
public static void DoAfter(TimeSpan waitFor, Action<Logger> action)
{
try {
ThreadStart work =() =>
{
Thread.Sleep(waitFor);
DatabaseLogger logger = new DatabaseLogger();
logger.Log("Executing " + action.Method.Name + ", " + DateTime.Now.ToLongTimeString());
try
{
action.Invoke(logger);
logger.Log("Successfully executed " + action.Method.Name + ", " + DateTime.Now.ToLongTimeString());
}
catch (Exception e)
{
logger.Log("Error in " + action.Method.Name + ": " + e.Message + ", " + DateTime.Now.ToLongTimeString());
}
logger.CloseDatabase();
};
Thread thread = new Thread(work);
thread.Start();
}
catch
{
}
}
Hintergrundinformation: In dem Produktionscode, der inneren async Anruf, in dem während des Debuggen ich erstellen Sie einfach eine neue Aufgabe, in einer Microsoft-Bibliothek erstellt wird, der nicht synchrone Methoden anbieten , so kann ich die Aufgabe nicht einfach "entfernen".
Verwenden Sie 'new Thread' nicht mit' async'! –
@DavidPine Warum nicht? Bitte erläutern. – Alexander
Die Verwendung von 'async' und' await' wird dies für Sie erledigen ... es sollte nicht notwendig sein, einen neuen Thread manuell zu starten, besonders auf einem Webserver. –