0

話の教訓は「UIスレッドを独り占めしないでください」であることに感謝しますが、UIスレッドにできるだけ長くとどまることで、KISSを試みましたが、転換点に達したばかりで、デザインを変更する必要があります。

しかし、とにかく.....デスクトップでは発生しない、デバイスで気付いたことがあります。UIスレッドを占有すると、キーがドロップされます。これは、問題を表示する非常にシンプルなアプリです。

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;
    }
}

カスタムボックスでこれを実行すると、4つのキーを連続して押すことができますが、ctrは2つしか増加しません。次に、(デスクトップの高速化を補うために)いくつかのゼロを追加してデスクトップで実行すると、すべてのキーが取得されます。

何が起きてる?

4

3 に答える 3

2
for (int i = 0; i < 1000000; i++)
            {

            }

時間遅延を提供するための空のループは、EVENT駆動型モデルの理解が不十分であることを示しています。

Windows CEには、デスクトップバージョンのWindowsとは十分に異なるイベントハンドラーがあり、Windowsはこのタイプの悪用を許容しますが、WindowsCEは許容しません。

制御をスケジューラーに適切に解放する遅延ルーチンを呼び出すのではなく、このような空のループで多くの処理時間を吸収する場合、イベントハンドラーは呼び出されません。イベントハンドラーが十分な頻度で呼び出されない場合、イベントは失われます。これらのイベントの一部を格納するさまざまなバッファがありますが、入力デバイス(キーボード、タッチスクリーンなど)によっては、これらのバッファが不十分または存在しない場合があります。

ここでのキッカーは、ポータブルデバイスのイベントハンドラーに大きなバッファーがないことです。デスクトップコンピュータには、キーボードとマウスの両方のアクション用の大量のバッファがあります。

他にも多くの違いがありますが、肝心なのは、これらの単純な空のループ遅延ではなく、実際にスレッドを適切に解放して適切に遅延させる必要があるということです。

ここでは、Windows CEタイマーの方が適切です。キーダウンルーチンを使用してタイマーを開始し、タイマーがトリガーされたら、必要なアクションを実行します。これにより、制御が解放されてUIに戻り、他のイベントを実行できるようになります。

また、Windows CEはマルチスレッド/マルチタスクですが、プログラムは一度に1つのものだけを実行していると考えるのが最善であることに注意してください。OSとイベントモデルがアプリイベントを送信している可能性があり(それらをバッファリングしていない)、アプリはそれらを無視してこの遅延ルーチンにとどまっています。そのループの実行中は、他のイベント(キーダウンを含む)は表示されません。システムの負荷とパフォーマンスに応じて、遅延は数ミリ秒から数百ミリ秒実行される可能性があります-実行するたびに同じ長さの時間を実行することを期待することはできません-実際のタイマーを使用するもう1つの理由。

-アダム

于 2009-01-16T18:49:16.523 に答える
1

メッセージがキューに入ると、WindowsCEはキーを「ドロップ」しません。私の推測では、キーボードドライバー自体がすべてのキーを取得していないため、キーを渡すことができないほど多くのクォンタムを使用していると思います。これは、キーボード自体を使用してハードウェアまたはドライバーの相互作用を除外する代わりに、PostKeybdMessageを呼び出すことで確認できます。

于 2009-01-16T18:46:26.500 に答える
1

The issue was to do with a bug in the BSP (apparently from some Freescale code) that meant that the keyboard driver was functioning at a much lower priority interrupt than was intended.

This is now fixed and everything works awesome fine. :)

于 2009-10-28T15:52:19.080 に答える