C# “;线程被中止”;异步webapi控制器中的错误

C# “;线程被中止”;异步webapi控制器中的错误,c#,asp.net,visual-studio-2012,asp.net-web-api,C#,Asp.net,Visual Studio 2012,Asp.net Web Api,我正在我的开发盒上运行VS 2012(更新2)/.NET 4.5/IIS Express 8.0/Win 7。 我使用的是异步WebAPI(不是WebAPI 2)控制器 最近,我开始注意到,当运行连接了VS调试器的WebAPI项目时,我会间歇性地“线程被中止” 错误。 我做了一些,我下意识的反应是这就是问题的原因 我花了一些时间深入挖掘,发现在检查异常对象时,所有属性都有以下错误, “无法计算表达式,因为代码已优化或本机框架位于调用堆栈顶部。” 单步执行代码时,错误发生在代码的不同部分,如中所示

我正在我的开发盒上运行VS 2012(更新2)/.NET 4.5/IIS Express 8.0/Win 7。 我使用的是异步WebAPI(不是WebAPI 2)控制器

最近,我开始注意到,当运行连接了VS调试器的WebAPI项目时,我会间歇性地“线程被中止” 错误。 我做了一些,我下意识的反应是这就是问题的原因

我花了一些时间深入挖掘,发现在检查异常对象时,所有属性都有以下错误, “无法计算表达式,因为代码已优化或本机框架位于调用堆栈顶部。” 单步执行代码时,错误发生在代码的不同部分,如中所示:

这个 建议使用
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;
    }
}
公共类SomeClass
{
私人住宅;
公共类()
{
str=新延迟(Init);
}
私有字符串Init()
{
尝试
{
字符串s=“无论如何”;
返回s;
}
捕获(例外情况除外)
{
掷骰子;
}
}
私有字符串GetInternalString()
{
返回str.值;
}
公共任务GetString()
{
返回Task.Factory.StartNew(()=>GetInternalString());
}
}
公共类TestController:ApicController
{
私有异步任务GetStringAsync()
{
SomeClass c=新的SomeClass();
var x=wait c.GetString();
返回x;
}
公共异步任务Get(int-id)
{
字符串s=等待GetStringAsync();
返回s;
}
}
更新: 我相信我已经解决了这个问题(代码示例已更新)。调试时,我将
str.Value
添加到Watch widow中,并在
string s=“whatever”上设置断点在单步执行代码时,我能够重新设置问题。
从“监视”窗口中删除
str.Value
会导致问题消失

我认为这与给出的解释有关 调试器正在终止线程以避免死锁。我只需要确认这是一种情况,而不是与使用
Task.Factory.StartNew

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

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

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


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

谢谢Stephen。我使用了.Result作为示例,因为我添加了一个人工任务。延迟模拟处理。实际上它看起来像Task.Factory.StartNew(()=>GetContactInternal(id))。在这种情况下,是的,它很危险。我有一个。我读了你的文章,但在这种情况下使用backgroundworkitem是不合适的。这些是异步控制器,用于返回任务,以便运行时了解后台处理。我仍然不明白为什么这会导致线程中止,而且只有在“监视”窗口中调试和检查变量时才会如此。只有在使用
wait
时,运行时才会意识到这一点。如果您只是用
StartNew
启动它们,而不对返回的任务执行任何操作,则运行时不会意识到这一点。请发布一个复制问题的最小代码示例。如果您否决了投票,请体面地解释原因。OP花了相当多的时间在这里构思和发布问题。如果你不能得到你所寻求的帮助,那么在网上发布毫无意义!请用真实的代码而不是延迟来显示代码,或者至少用带有真实方法签名的方法来显示带有主体注释的方法。我认为,在您努力“简化”it的过程中,您可能正在完全删除导致您的问题的代码。