Приложение зависает, но не вылетает? (VISUAL BASIC) - PullRequest
0 голосов
/ 04 ноября 2019

Таким образом, я работал над проектом для школы, и часть его должна вычислить координаты для движения снаряда, которые затем будут добавлены в серию точек на графике и нанесены на график в приложении. Единственная проблема заключается в том, что если скорость слишком высока (что увеличит общее время, необходимое для полета, и дальность полета, что приведет к большему набору координат), приложение зависнет, но не выйдет из строя. Он не показывает никакой ошибки, как это обычно бывает при использовании Visual Studio 2013.

Я приложу код для этого процесса, кто-нибудь может определить, почему он зависает и / или как его исправить?

Я только новичок, поэтому не очень разбираюсь в программировании, все, что поможет, будет с благодарностью.

For x As Integer = 0 To totalTime Step 0.01
    Dim xPos As Double = findXLocation(velocity, angle, x)
    Dim yPos As Double = findYLocation(velocity, angle, x, elevation, totalTime, heightOfProjectile, flightRange)

    Chart1.Series("Projection").Points.AddXY(xPos, yPos)

    Dim label As New CalloutAnnotation

    With label
        Chart1.Annotations.Add(label)
    End With
Next 

Один из способов ускорить расчеты, который я нашел, - уменьшить шаг(0,01 изначально) к чему-то более высокому, что означает, что будет сделано меньше вычислений. Но это приведет к большому количеству операторов If, поскольку операторы case также приводят к зависанию вычисления этих точек. Я также попытался установить переменную, названную 'increment', установленную как значение шага. Это можно было рассчитать разными способами - я изначально пытался increment = totalTime / 1000, но опять-таки это просто вызвало полное зависание приложения, несмотря на то, какая скорость будет введена.

findYLocation и findXLocation также могут быть полезны,и прилагаются ниже.

Public Function findYLocation(ByVal velocity As Double, ByVal angle As Double, ByVal time As Double, ByVal elevation As Double, ByVal totalTime As Double, ByVal heightOfProjectile As Double, ByVal flightRange As Double) As Double
    Dim y As Double

    y = -(0.5 * gConstant * sq(time)) + (findVerticalVelocity(velocity, angle) * time) + elevation
    ' y = Math.Round(y, 1)

    If y < 0 Then
        y = 0
    End If

    Return y
End Function

Public Function findXLocation(ByVal velocity As Double, ByVal angle As Double, ByVal time As Double) As Double
    Dim x As Double

    x = findHorizontalVelocity(velocity, angle) * time
    ' x = Math.Round(x, 1)

    If x < 0 Then
        x = 0
    End If

    Return x
End Function

Ответы [ 2 ]

1 голос
/ 04 ноября 2019

Проблема заключается в этой строке

For x As Integer = 0 To totalTime Step 0.01

x - это целое число, и когда вы добавляете к нему 0,01, оно никогда не будет увеличиваться. Сделай xa Double. На самом деле, вы можете избавить себя от головной боли, позволив компилятору определить правильный тип

For x = 0 To totalTime Step 0.01 ' it is now Double

, а также добавив Option Strict On в верхней части вашего файла кода, в любом случае проблема для вас найдется

For x As Integer = 0 To totalTime Step 0.01

Option Strict On запрещает неявное преобразование из 'Double' в 'Integer'

В другом ответе и комментариях предлагается отладить код. Конечно, отладка помогла бы вам здесь. Если бы я был тобой, я бы позволил ему работать, поставил точку останова в цикле For и проверил, что происходит. Было бы очевидно, что переменная цикла не увеличивается.

Согласно другому ответу, вы можете добавить Console.WriteLine в цикл. Эта строка будет хорошо работать внутри цикла

Console.WriteLine($"Inside For loop, x:{x}, xPos:{xPos}, yPos:{yPos}")

, что будет означать

Внутри цикла For, x: 0, xPos: 0, yPos: 10
Inside Forloop, x: 0, xPos: 0, yPos: 10
Inside For loop, x: 0, xPos: 0, yPos: 10
Inside For loop, x: 0, xPos: 0, yPos: 10
Внутри цикла For, x: 0, xPos: 0, yPos: 10

Там, где можно ожидать изменения значений. Они делают, когда это цикл Double

Inside For, x: 0, xPos: 0, yPos: 10
Inside For loop, x: 0.01, xPos: 0.0707106781186548, yPos: 11.6202267316012
Внутри для цикла, x: 0,02, xPos: 0,14142135623731, yPos: 12.3327679741871
Внутри для цикла, x: 0,03, xPos: 0.212132034355964, yPos: 12.8959725661313
Inside для цикла, x: 0,04, xPos: 0,246284: 13.3818748194396

Я все еще не думаю, что это завершено.

Нет причин выполнять весь цикл в пользовательском интерфейсе. Так что отделите вашу обработку и пользовательский интерфейс. Есть много способов достичь этого. Один использует Async / Await , и я считаю это самым простым способом. Поймите, что когда вы работаете за пределами пользовательского интерфейса, вам нужно будет вызывать обратные вызовы пользовательского интерфейса, чтобы делать там какие-либо обновления.

Самый большой удар по производительности, который вы создаете, - это добавление аннотации к диаграмме для каждого увеличения с 0,01. во время. Это действительно необходимо? Без добавления аннотаций построение происходит очень быстро. С аннотациями он быстро замедляется до ползания.

Вам нужно продолжать обработку, когда y достигнет нуля? Я добавил логику для выхода из цикла, как только это произойдет.

Обратите внимание, что Await отправит код с интерфейса, поэтому ваш интерфейс будет интерактивным во время работы. Вот код, который демонстрирует это. Обратите внимание, что аннотации добавляются каждые 0,1 секунды вместо 0,01. Они эффективно уничтожены. Вы можете дурачиться с ним, чтобы заставить его работать так, как вам нужно.

Private gConstant As Double = 9.8
Private totalTime As Double
Private velocity As Double
Private angle As Double
Private elevation As Double
Private heightOfProjectile As Double
Private flightRange As Double

Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    totalTime = 100
    velocity = 100
    angle = Math.PI / 4
    elevation = 100
    heightOfProjectile = 10
    flightRange = 10
    Chart1.ChartAreas(0).AxisX.Minimum = 0
    Chart1.Series("Projection").ChartType = SeriesChartType.FastLine
    Await Task.Factory.StartNew(AddressOf getPoints)
End Sub

Private Sub getPoints()
    For x As Double = 0 To totalTime Step 0.01
        Dim xPos As Double = findXLocation(velocity, angle, x)
        Dim yPos As Double = findYLocation(velocity, angle, x, elevation, totalTime, heightOfProjectile, flightRange)
        Dim l = x
        Chart1.Invoke(
            Sub()
                Chart1.Series("Projection").Points.AddXY(xPos, yPos)
                If CInt(100 * l) Mod 10 = 0 Then Chart1.Annotations.Add(New CalloutAnnotation())
            End Sub)
        Console.WriteLine($"Inside For loop, x:{x}, xPos:{xPos}, yPos:{yPos}")
        If yPos = 0 Then Exit For
    Next
End Sub

Public Function findYLocation(ByVal velocity As Double, ByVal angle As Double, ByVal time As Double, ByVal elevation As Double, ByVal totalTime As Double, ByVal heightOfProjectile As Double, ByVal flightRange As Double) As Double
    Return Math.Max(0, -0.5 * gConstant * sq(time) + findVerticalVelocity(velocity, angle) * time + elevation)
End Function

Private Function sq(value As Double) As Double
    Return value ^ 2
End Function

Public Function findXLocation(ByVal velocity As Double, ByVal angle As Double, ByVal time As Double) As Double
    Return Math.Max(0, findHorizontalVelocity(velocity, angle) * time)
End Function

Private Function findVerticalVelocity(velocity As Double, angle As Double) As Double
    Return Math.Sin(angle) * velocity
End Function

Private Function findHorizontalVelocity(velocity As Double, angle As Double) As Double
    Return Math.Cos(angle) * velocity
End Function

enter image description here

1 голос
/ 04 ноября 2019

Вы можете попытаться приостановить программу и проверить, какая операция вызывает ее зависание (кнопка слева, рядом с кнопкой остановки в Visual Studio). Pause button on the left

Также вы можете попытаться добавить некоторые записи в ваш код, чтобы увидеть, в чем проблема на самом деле.

Console.WriteLine("Logging")

Или даже время ваших расчетов (см. https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.stopwatch?view=netframework-4.8 для получения дополнительной информации)

...