2013-06-02 38 views
2

我正在嘗試更新我的擴展VSFileNav以使其與VS2012協同工作並對其進行一些改進。它應該列出Visual Studio解決方案中的所有文件,但我想將其擴展到列出方法/符號。爲什麼Visual Studio後臺線程如此緩慢?

我以前試過這個,從來沒有到過我的問題的底部。我發現,如果我在主線程上枚舉Solution->Projects->Project Items,它的速度相當快,但是如果我嘗試使用任何類型的線程,就會慢下來。我知道符號搜索需要從以前的嘗試,我已經沒有重新實現了一會兒的,但作爲一個例子,試圖找到所有的ProjectItem文件名時:

ProcessMainThread了:7毫秒
ProcessBackgroundThreadPool了:6661毫秒
ProcessCustomThread了:6750毫秒

片段我的代碼來運行這個,因爲我已經提到的所有它做的是枚舉所有的ProjectItems最終:

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(); 
} 

所以我的問題是,爲什麼在地球上幾乎1000X只要採取一個線程,我怎麼能產生不打算運行緩慢無阻塞的功能? - 牢記,當我開始在它的將文件中列舉符號比7毫秒更長的時間,否則我也不會太在意......

回答

5

您發現有-IS-沒有免費午餐法。經常應用於嘗試在大型對象模型中使用線程的法則。像任何大塊代碼一樣,VS自動化對象模型不是線程安全的。並且通過COM來保證安全,這是VS自動化的基礎。這確保您在工作線程上使用的EnvDTE屬性訪問器和方法實際上在創建該對象的線程上運行。從而確保線程安全。

這涉及大量的開銷。兩個線程上下文切換加上編組方法參數的成本加上編組結果的成本。加上所有者線程響應編組請求的延遲,通常是最大的塊和高度可變的,因爲它取決於它正在做的任何事情。相對於不通過公寓邊界的呼叫,典型的呼叫減速度爲x10000,因此您的測量值接近。

你通常通過創建工作線程的COM對象和轉向輔助線程在單線程給他們一個線程安全的家庭避免這種開銷。但至少有兩個原因不起作用,一個線程池線程始終是MTA。而最終的失敗,這些EnvDTE對象不是由你的代碼創建的。你可以對前者(Thread.SetApartmentState)做些什麼,但不能對後者做些什麼。

+0

感謝您的解釋漢斯,可能是我需要閱讀的東西。那麼有沒有合理的方法可以解決這個問題? - 如果使用線程比較慢,我可以考慮的唯一選擇是a)保持緩慢並在後臺執行一些工作,b)嘗試並找到路由到主線程的方法(不確定是否可以完成使用BeginInvoke等)或c)手​​動在後臺線程上以非COM方式工作。 – Ian

相關問題