Почему Windows CE пропускает ключевые события, если вы загружаете поток пользовательского интерфейса - PullRequest
0 голосов
/ 16 января 2009

Теперь я ценю, что мораль этой истории - «не забивайте нить пользовательского интерфейса», но мы пытались поцеловать ее, как можно дольше сохраняя ее в потоке пользовательского интерфейса, но я думаю, что мы только что достигли критической точки нам придется изменить наш дизайн.

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

using System;
using System.Windows.Forms;

namespace DeviceApplication14
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [MTAThread]
        static void Main()
        {
            Application.Run(new Form1());
        }

        private int ctr;

        public Form1()
        {
            InitializeComponent();
            KeyPreview = true;
            KeyDown += Form1_KeyDown;
        }

        void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            for (int i = 0; i < 1000000; i++)
            {

            }
            ctr++;
            button1.Text = ctr.ToString();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            ctr = 0;
            button1.Text = ctr.ToString();
        }

        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.button2 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(235, 137);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(329, 239);
            this.button1.TabIndex = 0;
            this.button1.Text = "button1";
            // 
            // button2
            // 
            this.button2.Location = new System.Drawing.Point(62, 291);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(72, 20);
            this.button2.TabIndex = 1;
            this.button2.Text = "Clear";
            this.button2.Click += new System.EventHandler(this.button2_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
            this.AutoScroll = true;
            this.ClientSize = new System.Drawing.Size(638, 455);
            this.Controls.Add(this.button2);
            this.Controls.Add(this.button1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }

        #endregion

        private Button button1;
        private Button button2;
    }
}

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

Что здесь происходит?

Ответы [ 3 ]

2 голосов
/ 16 января 2009
for (int i = 0; i < 1000000; i++)
            {

            }

Пустые циклы для обеспечения временных задержек свидетельствуют о плохом понимании модели, управляемой СОБЫТИЕМ.

Windows CE имеет достаточно отличающийся обработчик событий от настольной версии Windows, которая, в то время как Windows допускает такой тип злоупотребления, Windows CE не будет.

Если вы впитываете много времени обработки в пустые циклы, такие как этот, вместо того, чтобы вызывать подпрограмму задержки, которая должным образом возвращает управление планировщику, то обработчик событий вызываться не будет. Если обработчик событий вызывается недостаточно часто, вы потеряете события. Существуют различные буферы, в которых хранятся некоторые из этих событий, но в зависимости от устройств ввода (клавиатура, сенсорный экран и т. Д.) Эти буферы могут быть неадекватными или несуществующими.

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

Есть много других отличий, но суть в том, что вам действительно нужно правильно освободить поток и правильно отложить, а не эти простые задержки пустых циклов.

Таймер Windows CE здесь был бы более уместным - запускайте таймер с помощью процедуры нажатия клавиш, и, когда она срабатывает, выполните необходимое действие. Это вернет управление обратно в пользовательский интерфейс, чтобы могли запускаться другие события.

Кроме того, имейте в виду, что, хотя Windows CE является многопоточным / многозадачным, лучше всего рассматривать вашу программу как выполняющуюся только по одному за раз. ОС и модель событий могут отправлять события вашего приложения (а не буферизировать их), и ваше приложение находится в этой процедуре задержки, игнорируя их. Вы не увидите других событий (включая нажатия клавиш), пока выполняется этот цикл. В зависимости от нагрузки и производительности системы эта задержка может длиться от нескольких миллисекунд до сотен миллисекунд - вы не можете рассчитывать на то, что она будет работать одинаково долго каждый раз, когда запускается, - еще одна причина для использования реальных таймеров.

-Adam

1 голос
/ 28 октября 2009

Проблема была связана с ошибкой в ​​BSP (по-видимому, из некоторого кода Freescale), из-за которой драйвер клавиатуры работал с прерыванием с гораздо более низким приоритетом, чем предполагалось.

Теперь это исправлено, и все работает отлично. :)

1 голос
/ 16 января 2009

Windows CE не будет «сбрасывать» какие-либо ключи, как только сообщение попадет в очередь. Я предполагаю, что вы используете столько квантов, что сам драйвер клавиатуры не получает все клавиши и поэтому не может их передавать. Вы можете убедиться в этом, вызвав PostKeybdMessage вместо использования самой клавиатуры для исключения взаимодействия оборудования или драйвера.

...