Private Sub B1_Click(ByVal sender As System.
Object, ByVal e As System.EventArgs) Handles B1.Click Dim buffer As String REM Временный буфер для размещения участка текста длиной 12 символов
Dim pointer As Integer REM Указатель на место в тексте, которое помещается в буфер
Dim time As Single REM Смещение времени, заданное в поле T1
Dim a As Integer
Dim d As Single REM Время, извлечённое из файла с субтитрами *.srt (в переменной buffer)
REM Заносим начальные значения
time = Val(T1.Text)
T3.Text = ""
pointer = 0
REM Главный цикл обработки данных
Do
a = T2.Text.Length - pointer REM Вычисляем, какой участок текста скопировать в буфер
If a > 12 Then a = 12
If a < 0 Then a = 0
buffer = T2.Text.Substring(pointer, a)
If a < 12 Then Exit Do REM Выходим из цикла, если участок слишком мал (т. е. достигнут конец текста)
REM Проверка того, что буфере находится время
If buffer.Chars(2) = ":" And buffer.Chars(5) = ":" And buffer.Chars(8) = "," Then
d = Val(buffer.Substring(0, 2)) * 3600 + Val(buffer.Substring(3, 2)) * 60 + _
Val(buffer.Substring(6, 2)) + Val(buffer.Substring(9, 3)) / 1000
REM Смещение времени
d = d + time
If d < 0 Then d = 0
If d > 300000 Then d = 300000
REM Запись в буфер смещённого времени
a = Int(d)
buffer = a \ 36000 & a \ 3600 Mod 10
buffer = buffer & ":" & a \ 600 Mod 6 & a \ 60 Mod 10
buffer = buffer & ":" & a \ 10 Mod 6 & a Mod 10
a = Int((d - Int(d) + 0.0001) * 1000)
buffer = buffer & "," & a \ 100 & a \ 10 Mod 10 & a Mod 10
T3.Text = T3.Text & buffer
pointer = pointer + 12
Else
REM Если в буфере не время, то копируем один символ и идём дальше
T3.Text = T3.Text & buffer.Chars(0)
pointer = pointer + 1
End If
Loop
REM Копируем остаток данных из буфера
T3.Text = T3.Text & buffer
End Sub
Любая программа для виндовс, работает через очередь сообщений. Все нажатия кнопок, все отрисовки и пр. штуки происходят только после того, как программа получит нужное сообщение. При запуске программы, создается главный поток программы, где есть цикл получения и обработки сообщений. Ваше окно, получает сообщения из этой очереди. Если вы при нажатии кнопки повестите цикл, то программа будет работать в этом цикле пока он не завершится. В это время она не будет получать сообщения из очереди и соответсвенно не сможет реагировать ни на что. Потому нужно при каждой итерации цикла - протолкнуть очередь, что бы программа забрала скопивщиеся сообщения.
В .Net это делается путем вызова метода Application.DoEvent()
Но в этот метод не гарантирует хорошей работы программы. Все зависит от того что делается в цикле. В вашем случае - должно помочь.
Правильным решением будет создать отдельный параллельный поток, который не будет зависить от основного и будет выполнятся отдельно от основной программы. В этом случае, очередь сообщений не будет останавливаться и программа не будет тормозить. Однако программирование потоков, это довольно сложная задача. Нужны более глубокие знания о синхронизации потоков, мьютексах, семафорах и прочих радостях. Дело в том, что потоки не зависимы, а это значит что из вторичного потока нельзя обращаться к главному без синхронизации. Т.е. из второго потока, в не можете например записать строку в лейбу - программа упадет
https://docs.microsoft.com/ru-ru/dotnet/api/system.windows.forms.application.doevents?view=net-5.0
Тут проблема совершенно в другом. Проблема в том, что программа работает ДОЛГО, а этого не должно быть. Мне не жалко, что программа "висит" - это её дело, если бы она работала ПРАВИЛЬНО. Но дело в том, что обработка на процессоре "Celeron 333" 100 строк длится около минуты!
А 200 строк - уже почти 4 минуты. Зависимость квадратичная. В то время как я ожидал увидеть линейную зависимость.
Ну и кроме того, я знаю, что на языке C у меня программа работала всего 1 секунду. Почувствуйте разницу!
Стандартный файл субтитров у меня обрабатывался бы минут 20-25. Этого я не стал ждать.
Но я уже понял, в чем дело. Когда я работаю в Basic, исходным данным для меня является текстовой поле. Оно преобразуется в объект типа String. И чем длиннее этот объект, тем дольше происходит с ним любая операция. Зависимость линейная. А если учесть что число операций пропорционально длине этого объекта, мы получаем квадратичную зависимость.
То есть если бы ту же программу я записал в Visual C++ .Net, получилась бы та же самая ерунда.
Когда же я работаю в C, я беру данные из файла, а это линейная запись. Вот и получается время работы 1 секунда!
Как в любой трудной ситуации есть выход. И не один, а два.
1) Разбить исходный объект на много мелких длиной 1000 байтов. Работать только с мелким объектом. Последовательно.
2) Сразу, заранее перекодировать весь текст в целочисленный массив. Далее работать только с числами. По окончании работы перекодировать весь массив обратно в текстовый объект и выдать на экран.
Но поскольку я ленивый, я не буду с этим мучиться. Лишний геморрой.
https://docs.microsoft.com/ru-ru/dotnet/api/system.text.stringbuilder?view=net-5.0