更新时间:2023-12-05 10:05:46
是什么原因导致ThreadAbortException?
块引用>请参阅
ThreadAbortException
:当呼叫来中止方法中时引发的异常。避免使用所有手动发
相关code在DoAfter
方法。
请问有什么方法可以让周围的ThreadAbortException?
块引用>是的......利用
异步
和等待
关键字正确遵循***的编程实践和模式。下面是我建议的修改:
[HTTPGET]
公共异步任务<串GT; TestThreadAbortException()
{
InitToolkit(); //初始化记录仪,DB等。 VAR的结果=等待DoAfter(5.Seconds(),MyAction); 返回结果;
}标记您的控制器方法
任务< T>
回国,其中T
是返回类型。在这种情况下,字符串
。如果您需要简单地启动后台测井作业,然后返回到客户端,你应该考虑的QueueBackgroundWorkItem$c$c>.而不是使用
Thread.sleep代码
使用Task.Delay
,方法标记为工作
或任务< T>
是异步操作的再presentative公共异步任务< T> DoAfter< T>(时间跨度WAITFOR,Func键<记录器,任务< T>>动作)
{
等待Task.Delay(WAITFOR);
DatabaseLogger记录器=新DatabaseLogger();
logger.Log(执行+ action.Method.Name +,+ DateTime.Now.ToLongTimeString());
尝试
{
返回等待操作(记录);
logger.Log(成功执行+ action.Method.Name +,+ DateTime.Now.ToLongTimeString());
}
赶上(例外五)
{
logger.Log(错误+ action.Method.Name +:+ e.Message +,+ DateTime.Now.ToLongTimeString());
}
最后
{
logger.CloseDatabase();
}
}私人异步任务MyAction(记录器记录器)
{
VAR的结果=等待的MyMethod();
logger.Log(结果);
}私人异步任务<串GT;的MyMethod()
{
等待Task.Delay(20000);
返回测试;
}From IIS, when I am calling some background task in a new thread, it only runs through if the task does not contain certain asynchronous calls.
If I call a background task in a new thread, that does contain these asynchronous calls, it does return a
ThreadAbortException
, while the same Action, being executed synchronously insideApiController
, does run through, and a different action, called asynchronously, also runs through.Furthermore, when I call one action synchronously as well as the other action asynchronously, the asynchronous call fails as well.
- What does cause the
ThreadAbortException
?- Is there anything I can do to get around the
ThreadAbortException
?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 { } }
Background information: In the production code, the inner async call, where during debugging I just create a new task, is created inside a Microsoft library that does not offer synchronous methods, so I won't be able to just "remove the Task".
What causes the ThreadAbortException?
See
ThreadAbortException
: "The exception that is thrown when a call is made to the Abort method". Avoid using all the manualThread
related code in theDoAfter
method.Is there anything I can do to get around the ThreadAbortException?
Yes... utilize the
async
andawait
keywords correctly following best programming practices and patterns.Here are my suggested modifications:
[HttpGet] public async Task<string> TestThreadAbortException() { InitToolkit(); // Initialize Logger, DB etc. var result = await DoAfter(5.Seconds(), MyAction); return result; }
Mark your controller method as
Task<T>
returning, whereT
is the type to return. In this case astring
.If you need to simply start a background logging job and then return to the client, you should consider
QueueBackgroundWorkItem
. Instead of usingThread.Sleep
useTask.Delay
, mark methods asTask
orTask<T>
that are representative of asynchronous operations.public async Task<T> DoAfter<T>(TimeSpan waitFor, Func<Logger, Task<T>> action) { await Task.Delay(waitFor); DatabaseLogger logger = new DatabaseLogger(); logger.Log("Executing " + action.Method.Name + ", " + DateTime.Now.ToLongTimeString()); try { return await action(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()); } finally { logger.CloseDatabase(); } } private async Task MyAction(Logger logger) { var result = await MyMethod(); logger.Log(result); } private async Task<string> MyMethod() { await Task.Delay(20000); return "Test"; }