Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Visual studio 2012 为什么VisualStudio后台线程如此缓慢?_Visual Studio 2012_Envdte - Fatal编程技术网

Visual studio 2012 为什么VisualStudio后台线程如此缓慢?

Visual studio 2012 为什么VisualStudio后台线程如此缓慢?,visual-studio-2012,envdte,Visual Studio 2012,Envdte,我正在尝试更新我的扩展,使其与VS2012兼容,并对其进行一些改进。它应该列出VisualStudio解决方案中的所有文件,但我想扩展它以列出方法/符号 我以前试过这个,但从来没有找到问题的根源。我发现,如果我在主线程上枚举解决方案->项目->项目项,速度相当快,但是如果我尝试使用任何类型的线程,速度都会减慢。我知道,从以前的尝试(我还没有重新实现)中,符号搜索需要一段时间,但作为一个示例,在尝试查找所有ProjectItem文件名时: ProcessMain线程占用时间:7毫秒 Process

我正在尝试更新我的扩展,使其与VS2012兼容,并对其进行一些改进。它应该列出VisualStudio解决方案中的所有文件,但我想扩展它以列出方法/符号

我以前试过这个,但从来没有找到问题的根源。我发现,如果我在主线程上枚举
解决方案->项目->项目项
,速度相当快,但是如果我尝试使用任何类型的线程,速度都会减慢。我知道,从以前的尝试(我还没有重新实现)中,符号搜索需要一段时间,但作为一个示例,在尝试查找所有
ProjectItem
文件名时:

ProcessMain线程占用时间:7毫秒
ProcessBackgroundThreadPool花费:6661毫秒
处理时间:6750毫秒

正如我前面提到的,我运行该程序的代码片段就是枚举所有
项目项

public void TimeProcess()
{
    Stopwatch sw = Stopwatch.StartNew();

    ProcessMainThread();
    sw.Stop();
    Debug.WriteLine("ProcessMainThread took : " + sw.ElapsedMilliseconds + " ms");

    ProcessBackgroundThreadPool();

    ProcessCustomThread();
}

public void ProcessMainThread() 
{
    Process(); 
}

public void ProcessBackgroundThreadPool()
{
    System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback((o) => 
    {
        Stopwatch sw = Stopwatch.StartNew();
        Process();
        sw.Stop();
        Debug.WriteLine("ProcessBackgroundThreadPool took : " + sw.ElapsedMilliseconds + " ms");
    }));
}
public void ProcessCustomThread() 
{
    System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(() =>
    {
        Stopwatch sw = Stopwatch.StartNew();
        Process();
        sw.Stop();
        Debug.WriteLine("ProcessCustomThread took : " + sw.ElapsedMilliseconds + " ms");
    }));
    t.Start();
}

所以我的问题是,为什么在一个线程上要花费将近1000倍的时间,我怎样才能产生一个不会运行缓慢的非阻塞函数呢记住,当我开始枚举文件中的符号时,它将比7ms长得多,否则我不会太在意…

你正在发现没有免费午餐的规律。在大型对象模型中尝试使用线程时经常使用的规则。与任何大块代码一样,VS自动化对象模型不是线程安全的。COM是VS自动化的基础,它确保了系统的安全。这确保在工作线程上使用的EnvDTE属性访问器和方法实际上在创建对象的线程上运行。从而确保线程安全

这需要大量的开销。两个线程上下文开关加上封送方法参数的成本加上封送结果的成本。加上所有者线程响应封送处理请求的延迟,通常是最大的块,并且高度可变,因为它取决于它正在执行的任何其他操作。与未跨越公寓边界的呼叫相比,封送呼叫的典型减速为x10000,您的测量值接近


通常,通过在工作线程上创建COM对象,并在单线程单元中转动工作线程,给他们一个线程安全的家,可以避免这种开销。但至少有两个原因不起作用,线程池线程总是MTA。最终的失败是,这些EnvDTE对象不是由您的代码创建的。您可以对前者(Thread.SetApartmentState)做些什么,但不能对后者做什么

谢谢你的解释,汉斯,可能是我需要了解的东西。那么有什么合理的方法来解决这个问题吗如果使用线程很慢,我能想到的唯一替代方法是a)保持它的速度并在后台执行一些工作,b)尝试找到一种方法路由到主线程(不确定是否可以使用BeginInvoke等完成),或者c)在后台线程上以非COM方式手动执行工作。