2012-11-06 30 views
3

有人可以解釋一下,如何讓VB6比VB.NET更快地返回相同的API調用?VB.NET中的API調用比VB6中的調用慢得多

這裏是我的VB6代碼:

Public Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hWnd As Long) As Long 
Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long 


Public Function GetWindowTextEx(ByVal uHwnd As Long) As String 

Dim lLen& 
lLen = GetWindowTextLength(uHwnd) + 1 

Dim sTemp$ 
sTemp = Space(lLen) 

lLen = GetWindowText(uHwnd, sTemp, lLen) 

Dim sRes$ 
sRes = Left(sTemp, lLen) 

GetWindowTextEx = sRes 

End Function 

這裏是我的VB.NET代碼:

Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Integer, ByVal lpWindowText As String, ByVal cch As Integer) As Integer 

    Dim sText As String = Space(Int16.MaxValue) 
    GetWindowText(hwnd, sText, Int16.MaxValue) 

我跑了每個版本的1000倍。

VB6版本需要2.04893359351538毫秒。 VB.NET版本需要372.1322491699365毫秒。

Release和Debug版本都差不多。

這裏發生了什麼?

+4

的PInvoke沒有白吃的午餐,當你使用了錯誤的聲明,它得到徹底的危險。 .NET中的字符串是不可變的,你的pinvoke調用會改變字符串。你可以在pinvoke.net上找到正確的聲明 –

+0

即使在VB6中'Declare'就是「慢船」。使用typelib建立鏈接會繞開一些開銷。我懷疑任何東西都可以幫助.Net語言。 – Bob77

+0

@HansPassant謝謝您,如果您發佈此評論,我會選擇您的評論作爲答案。你仍然可以做到這一點,你有很好的選票。一個問題,請:http://www.pinvoke.net/default.aspx/user32/IsIconic.html VB.NET聲明似乎不完整。其他一些函數有這個「 _」,但這個沒有。那是因爲網站尚未完成,還是有原因? – tmighty

回答

7

不要使用* A版本,只需跳過後綴,使用StringBuilder而不是字符串:

Private Declare Auto Function GetWindowText Lib "user32" (ByVal hwnd As Integer, ByVal lpWindowText As StringBuilder, ByVal cch As Integer) As Integer 
Private Declare Function GetWindowTextLength Lib "user32" (ByVal hwnd As Integer) As Integer 

Dim len As Integer = GetWindowTextLength (hwnd) 
Dim str As StringBuilder = new StringBuilder (len) 
GetWindowText (hwnd, str, str.Capacity) 
+0

非常感謝。我不知道宣言會造成如此大的差異。 – tmighty

+1

@tmighty:Windows在內部是Unicode的,所以如果你使用* A版本,在進入/退出GetWindowText時,Windows必須將Ansi和Unicode之間的字符串進行轉換。使用StringBuilder可以確保.NET在進入/退出時不需要進行任何字符串編組。 –