简体   繁体   中英

Image Not Showing Up - Program Freezes

The program starts. When I click the Start button the original form disappears just as I intended, but then it just hangs there. No picture shows up. The CPU heats up and gets louder. It freezes and I sometimes have to CTRL+ALT+DELETE just to exit the program.


'Reaction.exe

'Picture comes up once, user presses left side of keyboard (Q,A,or Z)  
'Picture comes up a second time, user presses right side of keyboard (P,L,or M)
'A total of 10 .bmps, pictures show up randomly, a picture will only show up twice 
'Time (in millisecods) is recorded for each attempt 
'If user presses correct key, 
'For example if user presses 2 and it is the 2nd time the picture has shown up 
'Accuracy goes up a point (maximum of 10) 
'If user presses wrong key,  
'For example if user presses 2 even though the picture has only shown up once 
'Accuracy goes down a point (minimum of 0)


Public Class Form_Main


'Declare Globals'
Public X As Integer = 0 'Used in DisplayImage() function
Public I As Integer = 0 'Used for Times array and CalcTime() function
Public Num As Integer = 0   'Used in branches
Public Flag As Integer = 0
Public Accuracy As Integer = 0
Public Speed As Double = 0
Public Delay As Integer = 0
Public Timer_Start As Double = 0
Public Timer_End As Double = 0

'Arrays
'Times Array
Public Times(20) As Double  'Holds 20 times (since each picture will pop up twice)'

'Main Array
'Field = How many images will be used (Default is 10, for 10 pictures)
'Value:
'0 = Picture hasn't been used yet
'1 = Picutre has been used
'2 = Picture has already been used twice, and will not appear again
Dim MainArray(10) As Integer


' Start Button click (Main Function)
Private Sub Button_Start_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Start.Click
    ' Disable and hide the form
    RadioButton_Images.Visible = False
    RadioButton_Inkblots.Visible = False
    RadioButton_Words.Visible = False
    Button_Start.Visible = False
    Button_Reset.Visible = False
    RadioButton_Images.Enabled = False
    RadioButton_Inkblots.Enabled = False
    RadioButton_Words.Enabled = False
    Button_Start.Enabled = False
    Button_Reset.Enabled = False

    'Images branch
    If RadioButton_Images.Checked Then
        Images()
    End If

    'Show the Reset Button
    Button_Reset.Visible = True
    Button_Reset.Enabled = True
End Sub


'Functions
'Images() Function
Private Function Images() As Action
    Do Until (Num = 10)
        Timer_Start = 0
        Timer_End = 0
        Flag = 0
        Delay = Rand(3000, 6000)
        System.Threading.Thread.Sleep(Delay) '3-6 second delay
        DisplayImage()
        Timer_Start = TimeOfDay.Millisecond
        Do While (Flag = 0)
        Loop
        CalcTime()
    Loop
End Function


'Rand() Function (returns a random integer between (x,y) )
Private Function Rand(ByVal Low As Long, ByVal High As Long) As Long
    'randomize function
    Randomize()
    Rand = Int((High - Low + 1) * Rnd()) + Low
End Function


'DisplayImage() Function
Private Function DisplayImage() As Action
    Do Until PictureBox.Visible = True
        X = Rand(1, 10)  'Get a random number from 1 to 10

        Select Case X
            Case Is = 1
                If MainArray(X) = 0 Then                    'First time the picture is used
                    PictureBox.ImageLocation = "C:\Reaction\Images\1.bmp"
                    MainArray(X) = 1
                    PictureBox.Visible = True
                ElseIf MainArray(X) = 1 Then                'Second time the picture is up
                    PictureBox.ImageLocation = "C:\Reaction\Images\1.bmp"
                    MainArray(X) = 2
                    Num = Num + 1
                    PictureBox.Visible = True
                Else                                        'If MainArray(X) doesn't = 1 or 0
                End If                                      'Then endif and get another rand #
            Case Is = 2
                If MainArray(X) = 0 Then
                    PictureBox.ImageLocation = "C:\Reaction\Images\2.bmp"
                    MainArray(X) = 1
                    PictureBox.Visible = True
                ElseIf MainArray(X) = 1 Then
                    PictureBox.ImageLocation = "C:\Reaction\Images\2.bmp"
                    MainArray(X) = 2
                    Num = Num + 1
                    PictureBox.Visible = True
                Else
                End If
            Case Is = 3
                If MainArray(X) = 0 Then
                    PictureBox.ImageLocation = "C:\Reaction\Images\3.bmp"
                    MainArray(X) = 1
                    PictureBox.Visible = True
                ElseIf MainArray(X) = 1 Then
                    PictureBox.ImageLocation = "C:\Reaction\Images\3.bmp"
                    MainArray(X) = 2
                    Num = Num + 1
                    PictureBox.Visible = True
                Else
                End If
                ...
        End Select
    Loop
End Function


Private Function CalcTime() As Action
    'Calculates the time in milliseconds
    'Records to Times() array
    Times(I) = Timer_Start - Timer_End
    I = I + 1
End Function


Private Sub Form_Main_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress

    'Keypress Q, A, or Z if the picture is seen for the first time
    'Otherwise one accuracy point is deducted
    If e.KeyChar = "Q" Or "A" Or "Z" Or "q" Or "a" Or "z" Then
        If PictureBox.Visible = True Then
            If MainArray(X) = 1 Then
                Timer_End = TimeOfDay.Millisecond
                PictureBox.Image = Nothing
                PictureBox.Visible = False
                Accuracy = Accuracy + 1
                Flag = 1
            Else
                Timer_End = TimeOfDay.Millisecond
                PictureBox.Image = Nothing
                PictureBox.Visible = False
                Accuracy = Accuracy - 1
                Flag = 1
            End If
        End If
    End If

    'Keypress for second occurance
    If e.KeyChar = "P" Or "L" Or "M" Or "p" Or "l" Or "m" Then
        If PictureBox.Visible = True Then
            If MainArray(X) = 2 Then
                Timer_End = TimeOfDay.Millisecond
                PictureBox.Image = Nothing
                PictureBox.Visible = False
                Accuracy = Accuracy + 1
                Flag = 1
            Else
                Timer_End = TimeOfDay.Millisecond
                PictureBox.Image = Nothing
                PictureBox.Visible = False
                Accuracy = Accuracy - 1
                Flag = 1
            End If
        End If
    End If
End Sub



'Reset button
Private Sub Button_Reset_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Reset.Click
    'Reset all global variables
    X = 0
    I = 0
    Num = 0
    Flag = 0
    Accuracy = 0
    Speed = 0
    Delay = 0
    Timer_Start = 0
    Timer_End = 0
    'temporarily use I and X to clear out MainArray() and Times() array
    For I = 0 To I = 10
        MainArray(I) = 0
    Next

    For X = 0 To X = 20
        Times(X) = 0
    Next
    'Reset back to 0
    X = 0
    I = 0

    'Enable and show the form, hiding the reset button
    RadioButton_Images.Visible = True
    RadioButton_Inkblots.Visible = True
    RadioButton_Words.Visible = True
    Button_Start.Visible = True
    Button_Reset.Visible = False
    RadioButton_Images.Enabled = True
    RadioButton_Inkblots.Enabled = True
    RadioButton_Words.Enabled = True
    Button_Start.Enabled = True
    Button_Reset.Enabled = False
End Sub

End Class

Without going through all the code , I think the following fragment is the main problem:

Do While (Flag = 0)
Loop

I notice that you are setting the Flag in reaction to some KeyPress events further on, to make that work you'll have to change the loop, at the very least, to

Do While (Flag = 0)
  Application.DoEvents
Loop

But I would strongly suggest a re-design that doesn't need such a busy-loop

You have a pair of Do While loops (Do Until (Num = 10), Do While (Flag = 0)) that will never stop, so when the program hits them it will go into a never-ending "infinite loop".

You wrote:

Do While (Flag = 0)
   Loop

... but you need some code in between these two lines that will change the value of Flag to something other than 0, otherwise there is no way the computer can ever satisfy the condition, and it will fruoitlessly loop for ever. eg This hypothetical example would wait for the user to press the Escape key:

Do While (Flag = 0)
       If UserPressedEscape() Then Flag = 1
   Loop

The CPU heats up and the cooling fan runs at full blast because the program is frantically looping, using 100% CPU time.

(I imagine you expect the event-handling code in your program to execute "in the background" while your loop is running, but in reality the computer only does one thing at a time, and so it never exits the loop to be able to run your event handler. If the program were "multi threaded" then this would be possible, but the way it is written, it is "single threaded" so the program simply does one thing at a time, in sequence, so it never gets out of the loop)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM