У меня проблема с приложением, которое сводит меня с ума, и я действительно не знаю, что еще я могу сделать, чтобы продолжить расследование.
У меня есть простое приложение Windows Forms (32-разрядное, VB. net, Framework 4.5.1), которое очень странно ведет себя на только одном P C, относительно распределения памяти. На всех других компьютерах, которые я пробовал, работает нормально! ДОЛЖНО быть что-то в этом конкретном P C, но я не могу понять, что это такое, если не считать переустановки всего по одному ...
на всех ПК , за исключением одного , использование памяти приложением в порядке и не превышает go 10-20 Мегабайт. Только на одном P C, что происходит Будучи моей собственной разработкой P C, память продолжает увеличиваться и никогда не освобождается, пока не достигнет предела 2 ГБ Windows и не выдаст исключение Out of Memory. Я скопировал одни и те же двоичные файлы на 6 разных ПК (четыре Win7, два Win10) и подтвердил, что приложение работает (и стабильно) на всех этих ПК. Только на моем P C, даже когда приложение запускается без инициализации передачи, кажется, что оно занимает как минимум на 20 мегабайт больше по сравнению с другими ПК. Так что, что бы это ни было, должно быть что-то на P C, которое вызывает это.
Приложение использует SqlDataReader
с SqlBulkCopy
для передачи нескольких гигабайт данных из одной базы данных в другую. Перевод осуществляется месяц за месяцем. Все объекты SqlDataReader, SqlBulkCopy, SqlConnection и SqlCommand располагаются после каждого месяца, поскольку я заключаю их в блок Using
. Я даже звоню GC.Collect
в конце каждой итерации.
Я даже использовал профилировщик памяти Visual Studio, чтобы попытаться выяснить, что происходит, но все, что он говорит, это то, что большая часть памяти запрашивается команда SqlBulkCopy.WriteToServer
. Это не кажется особенно проницательным.
Теперь еще одно интересное замечание: если я использую метод Winapi EmptyWorkingSet
после каждой итерации (не показано в коде ниже), память Кажется, освобождается. Так почему же Do tnet сборщик мусора не делает то же, что и ожидалось, и почему только на одном P C ???
Вот код. Некоторые части изменены, чтобы удалить конфиденциальные вещи. Это приложение VB. Net Winforms, использующее. Net Framework 4.5.1. Это построено на VS 2017, Windows 10.
Любые советы о том, как на земле исследовать это дальше, за исключением начала удаления Windows Обновлений и другого программного обеспечения по одному с этой конкретной рабочей станции, будет принята с благодарностью.
Большое спасибо!
Private Sub CopyData()
' Database connection strings for source and destination db
Dim conn_string_source As String = "<CONFIDENTIAL DATA MASKED>",
conn_string_destination As String = "<CONFIDENTIAL DATA MASKED>"
' For progress report.
Dim rows_total As Long,
rows_done As Long
'
' Find total rows to transfer.
' For progress report.
'
Using _
conn_src As New SqlConnection(conn_string_source),
cmd As New SqlCommand("Select Count(*) From dbo.SOURCE_TABLE", conn_src)
rows_total = CLng(cmd.ExecuteScalar())
Console.WriteLine("{0:#,##0} total rows to transfer.", rows_total)
End Using
'
' Transfer rows for one year, one month at a time.
' Dispose connections, readers and bulkcopy class at end of each month.
'
For which_month = 1 To 12
Using _
conn_dest As New SqlConnection(conn_string_destination),
conn_src As New SqlConnection(conn_string_source),
bc = New SqlClient.SqlBulkCopy(conn_dest)
'
' For progress report.
' Calculate rows for this month.
'
Dim rows_this_month As Long
Using cmd = New SqlCommand("Select Count(*)
From dbo.SOURCE_TABLE
Where posting_month = @mm", conn_src)
cmd.Parameters.AddWithValue("@mm", which_month)
rows_this_month = cmd.ExecuteScalar()
End Using
'
' Setup the Bulk Copy operation
'
bc.DestinationTableName = "dbo.TARGET_TABLE"
bc.BulkCopyTimeout = 0 ' Never timeout
bc.BatchSize = 3000 ' Rows per batch. This values seems efficient enough.
bc.NotifyAfter = 250 ' Raise notification event after every this number of rows copies.
' Microsoft says for better memory usage, though tests indicate doesn't make difference.
bc.EnableStreaming = True
' Notify us every few rows to know how much was finished.
AddHandler bc.SqlRowsCopied,
Sub(sndr, rr)
Console.WriteLine(" ...{0:#,##0} / {1:#,##0}", rr.RowsCopied, rows_this_month)
End Sub
'
' Perform the actual transfer.
' Feed a reader to the SqlBulkCopy operation.
'
Using cmd As New SqlCommand("Select *
From dbo.SOURCE_TABLE
Where posting_month = @mm", conn_src)
cmd.Parameters.AddWithValue("@mm", which_month)
Using rdr = cmd.ExecuteReader()
bc.WriteToServer(rdr)
End Using
End Using
rows_done += rows_this_month
Console.WriteLine(" GRAND TOTAL: {0:#,##0} / {1:#,##0}", rows_done, rows_total)
End Using
GC.Collect()
Next
End Sub