【问题标题】:API call in VB.NET much slower than in VB6VB.NET 中的 API 调用比 VB6 慢得多
【发布时间】:2012-11-07 06:48:01
【问题描述】:

有人能解释一下为什么使用 VB6 比使用 VB.NET 更快地返回相同的 API 调用吗?

这是我的 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 版本差不多。

这里发生了什么?

【问题讨论】:

  • Pinvoke 不是免费的,当你使用错误的声明时,它会变得非常危险。 .NET 中的字符串是不可变的,您的 pinvoke 调用正在改变一个字符串。您可以在 pinvoke.net 找到正确的声明
  • 即使在 VB6 中Declare 也是“慢船”。使用类型库建立链接绕过了一些开销。我怀疑任何东西都可以帮助 .Net 语言。
  • @HansPassant 谢谢,如果您这样发布,我会选择您的评论作为答案。你仍然可以这样做,你得到了很好的选票。请提出一个问题:pinvoke.net/default.aspx/user32/IsIconic.html VB.NET 声明对我来说似乎不完整。其他一些函数有这个" _",但是这个没有。是因为网站还没有完成,还是有什么原因?
  • 您说您运行了 1000 次,但您是否忽略了 .Net 端的前几次运行以解释 JIT 编译?看看你的计时方法会很有趣。

标签: vb.net performance vb6


【解决方案1】:

不要使用*A版本,直接跳过后缀,用StringBuilder代替String:

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)

【讨论】:

  • 非常感谢。我不知道声明会产生如此大的影响。
  • @tmighty:Windows 内部是 Unicode,所以如果您使用 *A 版本,Windows 必须在进入/退出到 GetWindowText 时将字符串在 Ansi 和 Unicode 之间转换。并且使用 StringBuilder 确保 .NET 在进入/退出时也不必进行任何字符串编组。
猜你喜欢
  • 2013-12-06
  • 1970-01-01
  • 2011-10-27
  • 1970-01-01
  • 2013-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多