无论我尝试什么,我都无法在KeyDown上退出循环

时间:2015-08-20 11:08:32

标签: vb.net loops class-library

这真的让我感到沮丧。

基本上,这是我为GTA IV编写的脚本的一部分(当它完成时我可能会在我的网站上发布mod)并且我需要在用户按下游戏中定义的键时退出此循环。当然,我无法使用KeyPreview因为这是类库(GTA IV插件必须使用.net.dll)。

这是我到目前为止所尝试的内容(显然不是完整代码),正如许多网站所建议的那样:

循环:

Sub CarFunctions()
    Dim veh = Player.Character.CurrentVehicle
    Do
        Application.DoEvents()
        If CancelLoop = True Then
            Exit Do
        End If
        Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, True)
        Native.Function.Call("FORCE_CAR_LIGHTS", veh, 1)
        Wait(500)
        Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, False)
        Native.Function.Call("FORCE_CAR_LIGHTS", veh, 2)
        Wait(500)
    Loop
End Sub

KeyDown事件:

Private Sub VehicleControls_KeyDown(sender As Object, e As GTA.KeyEventArgs) Handles Me.KeyDown
    Try
        Dim veh = Player.Character.CurrentVehicle
        If e.Key = Keys.NumPad5 Then
            CancelLoop = True
        End If
    Catch ex As Exception
        Game.Console.Print(ex.ToString)
    End Try
End Sub

我知道,问题是程序在循环中没有检测到任何按键事件。我尝试使用多线程,但它在游戏中引发异常,我不能使用调用方法。

提前谢谢。

3 个答案:

答案 0 :(得分:0)

一般来说,“退出控制结构”关键词,例如exit do,应该避免使用。

https://msdn.microsoft.com/en-us/library/eked04a7.aspx

Dim index As Integer = 0
Do
    Debug.Write(index.ToString & " ")
    index += 1
Loop Until index > 10

我认为循环直到你正在寻找。您可能必须使用while循环而不是do while来支持您的特定逻辑。这是我的尝试。

Sub CarFunctionsTask()
  Task.Factory.StartNew(Sub()
    Dim veh = Player.Character.CurrentVehicle
    Do
        If CancelLoop = False Then
            Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, True)
            Native.Function.Call("FORCE_CAR_LIGHTS", veh, 1)
            Wait(500)
            Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, False)
            Native.Function.Call("FORCE_CAR_LIGHTS", veh, 2)
            Wait(500)
        End If

    Loop Until CancelLoop
  End Sub)
End Sub

答案 1 :(得分:0)

我认为codemonkeyliketab接近答案,因为循环需要在后台线程上运行才能阻止keypress事件。我会推荐类似于他所做的事情,但使用调用上下文来执行Native.Function.Call行,如下所示:

Sub CarFunctions()
    Dim veh = Player.Character.CurrentVehicle
    Dim callingContext = System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext

    System.Threading.Tasks.Task.Factory.StartNew(
        Sub()
            While CancelLoop = False
                Dim t As Task
                t = System.Threading.Tasks.Task.Factory.StartNew(
                    Sub()
                        Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, True)
                        Native.Function.Call("FORCE_CAR_LIGHTS", veh, 1)
                    End Sub,
                    System.Threading.CancellationToken.None,
                    System.Threading.Tasks.TaskCreationOptions.None,
                    callingContext)
                t.Wait()
                Wait(500)
                t = System.Threading.Tasks.Task.Factory.StartNew(
                    Sub()
                        Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, False)
                        Native.Function.Call("FORCE_CAR_LIGHTS", veh, 2)
                    End Sub,
                    System.Threading.CancellationToken.None,
                    System.Threading.Tasks.TaskCreationOptions.None,
                    callingContext)
                t.Wait()
                Wait(500)
            End While
        End Sub)
End Sub

答案 2 :(得分:0)

在Mike Guthrie和codemonkeyliketab的帮助下,我设法通过在循环中使用isKeyPressed()来解决问题(不是很完美):

Do
    If Me.isKeyPressed(Keys.Decimal) Then
        Exit Do
    End If
    Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, True)
    Native.Function.Call("FORCE_CAR_LIGHTS", veh, 1)
    Wait(500)
    Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, False)
    Native.Function.Call("FORCE_CAR_LIGHTS", veh, 2)
    Wait(500)
Loop

感谢您的所有答案。