【问题标题】:C# reading joystick input without blocking UIC#读取操纵杆输入而不阻塞UI
【发布时间】:2014-11-30 03:13:31
【问题描述】:

这对你们中的一些人来说可能听起来很奇怪,但我无法找出正确的方法来读取操纵杆输入而不阻塞我的 UI 表单。我在网上找到了这个例子:

static void Main()
{
    // Initialize DirectInput
    var directInput = new DirectInput();

    // Find a Joystick Guid
    var joystickGuid = Guid.Empty;

    foreach (var deviceInstance in directInput.GetDevices(DeviceType.Gamepad, 
                DeviceEnumerationFlags.AllDevices))
        joystickGuid = deviceInstance.InstanceGuid;

    // If Gamepad not found, look for a Joystick
    if (joystickGuid == Guid.Empty)
        foreach (var deviceInstance in directInput.GetDevices(DeviceType.Joystick, 
                DeviceEnumerationFlags.AllDevices))
            joystickGuid = deviceInstance.InstanceGuid;

    // If Joystick not found, throws an error
    if (joystickGuid == Guid.Empty)
    {
        Console.WriteLine("No joystick/Gamepad found.");
        Console.ReadKey();
        Environment.Exit(1);
    }

    // Instantiate the joystick
    var joystick = new Joystick(directInput, joystickGuid);

    Console.WriteLine("Found Joystick/Gamepad with GUID: {0}", joystickGuid);

    //Query all suported ForceFeedback effects
    var allEffects = joystick.GetEffects();
    foreach (var effectInfo in allEffects)
        Console.WriteLine("Effect available {0}", effectInfo.Name);

    //Set BufferSize in order to use buffered data.
    joystick.Properties.BufferSize = 128;

    // Acquire the joystick
    joystick.Acquire();

    // Poll events from joystick
    while (true)
    {
        joystick.Poll();
        var datas = joystick.GetBufferedData();
        foreach (var state in datas)
            Console.WriteLine(state);
    }
}

我已经安装了sharpdx,我可以在控制台中看到操纵杆轴输出。

现在我想在我的 UI 上的单独文本框中显示每个轴数据。于是我改了几行代码:

joystick.Poll();
var data = joystick.GetBufferedData();
foreach (var state in data) 
{
    if (state.Offset == JoystickOffset.X)
    {
       textBox1.Text = state.Value.ToString();
    }
}

所以这应该将数据传递给文本框。如果我在这里写Console.Writeline(state.Value) 我会得到我想要显示的数据。问题是,这个while loop 会阻塞 UI。

我想把这个 while 循环放在private void timer_tick 中,并设置大概 10 毫秒的刷新率。但我不知道如何在单独的函数中访问像 var joystick 这样的变量。我还读到这可以通过异步编程来完成。可悲的是我现在被困住了。

谁能帮助我尽可能简单地解决这个问题?代码示例会很棒。

【问题讨论】:

  • 我可能有答案,但我不是 C# 开发人员。变量 data 是一个元素数组,在 foreach 循环中,变量 'state' 是该迭代的元素。对吗?
  • 是 WinForm 还是 WPF?

标签: c# asynchronous joystick


【解决方案1】:

假设您使用 WinForm 进行编码(从您的问题中的 blocking my UI form 推断)。

从设计器向您的表单添加一个计时器。

并在表单的 .ctor 中添加这些行:

public partial class JoyStickForm : Form
{
    public JoyStickForm()
    {
        InitializeComponent();

        // ...Other initialization code has been stripped...

        // Instantiate the joystick
        var joystick = new Joystick(directInput, joystickGuid);

        //Console.WriteLine("Found Joystick/Gamepad with GUID: {0}", joystickGuid);

        timer1.Interval = 100; 
        timer1.Tick += (s, e) =>
            {
                joystick.Poll();
                var lastState = joystick.GetBufferedData().Last(); //only show the last state

                if (lastState != null)
                {
                    if (lastState.Offset == JoystickOffset.X)
                    {
                        textBox1.Text = lastState.Value.ToString();
                    }
                }
            };

        //start the timer
        timer1.Enabled = true;
    }
}

解释:

  1. 每秒 100 次的刷新率是不必要的快,请记住大多数显示器的刷新率约为 60 Hz。我设置为 100 毫秒(每秒刷新 10 次),这是可以接受的。

  2. 使用lambda expression,您可以从计时器的滴答处理程序中访问var joystick 等变量。

  3. 在每次刷新时,只有数据中的最后一个状态会显示到TextBox

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-16
    • 2012-10-22
    • 1970-01-01
    相关资源
    最近更新 更多