异步 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相关的真正编码错误

异步 webapi 控制器中的“线程正在中止”错误

在 Web 应用程序中使用 Task.Factory.StartNew 是否正确/安全?

不。您应该只在处理程序中执行所需的操作,而无需使用其他后台线程。

您发布的代码不应导致虚假线程中止,因为它在后台线程上阻塞 ( .Result (。如果你的代码通过StartNew启动后台工作,并且不等待结果(await.Result.Wait()(,那么这是危险的,可能会导致虚假线程中止。但是,即使此代码不会导致线程中止,它对StartNew的使用效率也低于直接在请求上下文中执行工作的效率。

只需将任何StartNew(() => MyCode()).Result替换为 MyCode() .