异步 webapi 控制器中的“线程正在中止”错误
本文关键字:错误 webapi 控制器 异步 线程 | 更新日期: 2023-09-27 18:24:47
我在我的开发盒上运行VS 2012(更新2(/.NET 4.5/IIS Express 8.0/Win 7。我正在使用异步WebAPI(不是Web api 2(控制器。
最近,我开始注意到,在附加了 VS 调试器的情况下运行 Web api 项目时,我出现间歇性"线程正在中止"错误。我最近对Visual Studio进行了一些更改,我的膝跳反应是这就是问题的原因。
我花了一些时间深入挖掘,我注意到在检查异常对象时,所有属性都有以下错误,"无法计算表达式,因为代码已优化或本机帧位于调用堆栈之上。">当单步执行代码时,错误发生在代码的不同部分,如 Rick Strall 的帖子所示:
这个帖子表明它可能表示使用Task.Factory.StartNew
启动后台任务
在 Web 应用程序中使用 Task.Factory.StartNew
是否正确/安全?它是否会导致任何问题(例如在托管进程(如 ASP.NET(中运行时可能终止后台任务(。大多数操作都是 CRUD 样式的操作,本身运行时间不长。
此外,在IIS Express/IIS 7.5中正常运行(未连接调试器(时,尚未发生此问题。
下面是一个代码片段,它捕获了处理性质的本质和异步控制器的结构。
任何见解将不胜感激。
public class SomeClass
{
private Lazy<string> str;
public SomeClass()
{
str = new Lazy<string>(Init);
}
private string Init()
{
try
{
string s = "whatever";
return s;
}
catch (Exception ex)
{
throw ex;
}
}
private string GetInternalString()
{
return str.Value;
}
public Task<string> GetString()
{
return Task.Factory.StartNew(() => GetInternalString());
}
}
public class TestController : ApiController
{
private async Task<string> GetStringAsync()
{
SomeClass c = new SomeClass();
var x = await c.GetString();
return x;
}
public async Task<string> Get(int id)
{
string s = await GetStringAsync();
return s;
}
}
更新: 我相信我找到了问题所在(代码示例已更新(。在调试时,我向手表寡妇添加了str.Value
,并在string s = "whatever";
上设置了一个断点 单步执行代码,我能够重现问题。从监视窗口中移除str.Value
会导致问题消失。
我认为这与这篇SO帖子中给出的解释有关调试器正在终止线程以避免死锁。我只需要验证情况是否如此,而不是与使用Task.Factory.StartNew
相关的真正编码错误
在 Web 应用程序中使用 Task.Factory.StartNew 是否正确/安全?
不。您应该只在处理程序中执行所需的操作,而无需使用其他后台线程。
您发布的代码不应导致虚假线程中止,因为它在后台线程上阻塞 ( .Result
(。如果你的代码通过StartNew
启动后台工作,并且不等待结果(await
、.Result
或.Wait()
(,那么这是危险的,可能会导致虚假线程中止。但是,即使此代码不会导致线程中止,它对StartNew
的使用效率也低于直接在请求上下文中执行工作的效率。
只需将任何StartNew(() => MyCode()).Result
替换为 MyCode()
.