【发布时间】:2016-05-09 13:10:05
【问题描述】:
在 IIS 中,当我在新线程中调用某个后台任务时,它只会在任务不包含某些异步调用时运行。
如果我在包含这些异步调用的新线程中调用后台任务,它会返回一个ThreadAbortException,而在ApiController 中同步执行的相同操作确实会运行,并且会执行不同的操作,异步调用,也贯穿。
此外,当我同步调用一个动作以及异步调用另一个动作时,异步调用也会失败。
- 是什么导致
ThreadAbortException? - 有什么办法可以绕过
ThreadAbortException?
代码:
[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
{
}
}
背景信息:在生产代码中,内部异步调用(在调试期间我只是创建一个新任务)是在不提供同步方法的 Microsoft 库中创建的,因此我将无法仅“删除任务”。
【问题讨论】:
-
不要将
new Thread与async一起使用! -
@DavidPine 为什么不呢?请详细说明。
-
使用
async和await会为你处理这个问题......应该不需要手动启动一个新线程,尤其是在网络服务器上。 -
"The async and await keywords don't cause additional threads to be created." 好吧,我想创建一个后台线程,它不应该被前台进程等待,即使在前台进程完成后也应该继续。不完全确定如何做到这一点......
-
现在构建答案
标签: c# .net multithreading iis asynchronous