Как выйти из цикла, используя ввод с клавиатуры в C # - PullRequest
1 голос
/ 27 сентября 2019

Я использую C # в .Net Framework 8.0.Я хочу выйти из цикла, используя ввод с клавиатуры.

Ниже кода C #,

1) Если я удалю «MessageBox.Show (State.ToString ());», я не смогуизбежать цикла while.

2) Если я добавлю «MessageBox.Show (State.ToString ());», я смогу избежать цикла while.Но это не идеально.Потому что после того, как я вижу MessageBox «false», я должен нажать «A» и Enter.Затем Next Step, State изменяется на «true».И я вижу "true"> "Введено !!!"> "Пока Loop сломан !!!"Окно сообщения.

а) В чем разница 1) и 2).

б) Как выйти из цикла, используя ввод с клавиатуры?Легко.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Windows.Input;

namespace WF_Templete_
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void bt_Start_Click(object sender, EventArgs e)
        {
            while (true)
            {
                bool State = (System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.A) == true);
                // MessageBox.Show(State.ToString());

                if (State)
                {
                    MessageBox.Show("Entered !");
                    break;
                }
            }
            MessageBox.Show("While Loop is Broken !!!");
        }

    }
}

Ответы [ 2 ]

1 голос
/ 27 сентября 2019

Самое простое решение - добавить в цикл Application.DoEvents () .Это позволяет вашему коду обрабатывать события, которые в противном случае игнорировались бы во время замкнутого цикла.

В идеале вы хотели бы запустить свою бизнес-логику вне потока пользовательского интерфейса, используя шаблон MVC или MVVM, который затем оставил бы вас с отзывчивым пользовательским интерфейсом, с которым можно взаимодействовать, пока выполняется внутренняя обработка.

            while (true)
            {
                Application.DoEvents();
                bool State = (System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.A) == true);
                // MessageBox.Show(State.ToString());

                if (State)
                {
                    MessageBox.Show("Entered !");
                    break;
                }
            }
0 голосов
/ 27 сентября 2019

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

Один из способов подойти к этому -инкапсулируйте ожидание кнопки USB или отмену в классе, например, так:

public sealed class UsbButtonWaiter
{
    public UsbButtonWaiter(CancellationToken cancellation)
    {
        _cancellation = cancellation;
    }

    public async Task<bool> WaitForUsbButtonAsync()
    {
        var waitForUsbButton    = Task.Run(this.waitForUsbButton);
        var waitForCancellation = new Task(() => throw new InvalidOperationException(), _cancellation);

        return await Task.WhenAny(waitForUsbButton, waitForCancellation) == waitForUsbButton;
    }

    void waitForUsbButton()  // No idea how your code works for this, so here's a simulation.
    {
        Thread.Sleep(30000); // Simulate it taking 30s for the USB button to be pressed.
    }

    readonly CancellationToken _cancellation;
}

Затем вы можете использовать токен отмены для отмены ожидания нажатия кнопки USB.

В качестве примера того, какчтобы использовать это в форме, здесь я создал форму с одной кнопкой с именем button1 (по умолчанию при добавлении новой кнопки в форму).

Когда вы нажимаете эту кнопку, код будетначните ждать нажатия кнопки USB или, когда пользователь нажмет клавишу A на клавиатуре.Вы можете проверить этот код, создав приложение Windows Forms по умолчанию и поместив кнопку по умолчанию в основную форму (которая будет называться Form1 по умолчанию).

Затем добавьте следующий код в Form1:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);

        if (_cancellation == null)
            return;

        if (e.KeyCode == Keys.A)
            _cancellation.Cancel();
    }

    async void button1_Click(object sender, EventArgs e)
    {
        if (_cancellation != null) // Already waiting?
            return;

        button1.Enabled = false;
        button1.Text = "Waiting...";

        _cancellation = new CancellationTokenSource();
        UsbButtonWaiter waiter = new UsbButtonWaiter(_cancellation.Token);

        bool wasUsbButtonPressed = await waiter.WaitForUsbButtonAsync();

        if (wasUsbButtonPressed)
            MessageBox.Show("USB button was pressed");
        else
            MessageBox.Show("Cancel key was pressed");

        button1.Enabled = true;
        button1.Text = "button1";
    }

    CancellationTokenSource _cancellation;
}

Если вы запустите это приложение и нажмете button1, его текст изменится на Waiting... и отключится.

Тогда ничего не произойдет, пока вы не нажмете A или 30 с, после чего появится окно сообщения, сообщающее, была ли нажата кнопка USB или пользователь отменен, и кнопка будет повторно включена.

(Обратите внимание, что, конечно, кнопка USBникогда не нажимается, поскольку это всего лишь симуляция, но вы можете заменить соответствующий код.)

...