我在我的开发箱上运行VS 2012(Update 2)/ .NET 4.5 / IIS Express 8.0 / Win 7。 我正在使用异步WebAPI(而不是web api 2)控制器。
最近,我开始注意到在运行带有VS调试器的web api项目时,我正在断断续续的" Thread正在被中止" 错误。 我做了一些changes to Visual Studio recently并且我的膝盖反射是这个问题的原因。
我花了一些时间深入挖掘,我注意到在检查异常对象时,所有属性都有以下错误, "无法评估表达式,因为代码已优化或本机框架位于调用堆栈之上。" 如Rick Strahl's post:
中所示,当单步执行代码时,错误会发生在代码的不同部分这SO post
表明它可能表示使用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
添加到Watch寡妇并在string s = "whatever";
上设置断点。单步执行代码我能够重现问题。
从观察窗口中删除str.Value
会导致问题消失。
我认为这与in this SO post给出的解释有关
并且调试器正在杀死线程以避免死锁。我只需要验证是否是这种情况,而不是与使用Task.Factory.StartNew
答案 0 :(得分:1)
在Web应用程序中使用Task.Factory.StartNew是否正确/安全?
没有。您应该在处理程序中执行您需要的操作,而不使用其他后台线程。
您发布的代码不应导致虚假线程中止,因为它在后台线程(.Result
)上阻塞。如果您的代码通过StartNew
开始后台工作并且不等待结果(await
,.Result
或.Wait()
),那么危险并可能导致虚假线程中止。但是,即使此代码不会导致线程中止,它使用StartNew
的效率也不如直接在请求上下文中完成。
只需将StartNew(() => MyCode()).Result
替换为MyCode()
。