Application.DoEvents() の使用 質問する

Application.DoEvents() の使用 質問する

Application.DoEvents()C# で使用できますか?

この機能は、VB6 とほぼ同じように、GUI がアプリの残りの部分に追いつくことを可能にする方法ですかDoEvents?

ベストアンサー1

うーん、DoEvents() の不朽の神秘。これに対しては大きな反発がありましたが、なぜそれが「悪い」のかを実際に説明する人は誰もいません。「構造体を変更しないでください」というのと同じ種類の知恵です。えーっと、それがそんなに悪いのなら、なぜランタイムと言語は構造体の変更をサポートするのでしょうか? 同じ理由です。正しく行わなければ、自分の足を撃つことになります。簡単に。そして、正しく行うには、それが何をするのかを正確に知る必要がありますが、DoEvents() の場合、それは決して理解するのが簡単ではありません。

すぐにわかるように、ほとんどすべての Windows Forms プログラムには、実際には DoEvents() の呼び出しが含まれています。これは巧妙に隠されていますが、別の名前、つまり ShowDialog() で呼ばれています。DoEvents() により、アプリケーションの他のウィンドウをフリーズさせることなくダイアログをモーダルにすることができます。

ほとんどのプログラマーは、独自のモーダル ループを作成するときに、ユーザー インターフェイスがフリーズしないように DoEvents を使用したいと考えています。確かにその目的を達成できます。Windows メッセージをディスパッチし、ペイント要求を配信します。ただし、問題は選択的ではないことです。ペイント メッセージをディスパッチするだけでなく、他のすべてのメッセージも配信します。

また、問題を引き起こす通知のセットがあります。それらはモニターの約 3 フィート前から来ます。たとえば、DoEvents() を呼び出すループの実行中に、ユーザーはメイン ウィンドウを閉じることができます。これは機能し、ユーザー インターフェイスは消えます。しかし、コードは停止せず、ループの実行が続いています。これはよくありません。非常によくありません。

さらに、ユーザーが同じメニュー項目またはボタンをクリックすると、同じループが開始される可能性があります。これで、DoEvents() を実行する 2 つのネストされたループが作成され、前のループは中断され、新しいループが最初から開始されます。これは機能する可能性もありますが、可能性は低いです。特に、ネストされたループが終了し、中断されたループが再開され、すでに完了したジョブを終了しようとする場合です。これが例外で失敗しないのであれば、データは間違いなくめちゃくちゃになります。

ShowDialog() に戻ります。これは DoEvents() を実行しますが、別の処理も行うことに注意してください。ダイアログ以外のアプリケーション内のすべてのウィンドウを無効にします。これで 3 フィートの問題が解決されたので、ユーザーはロジックを混乱させることはできません。ウィンドウを閉じる、およびジョブを再開する両方の障害モードが解決されます。言い換えると、ユーザーがプログラムに別の順序でコードを実行させる方法はありません。コードをテストしたときと同じように、予測どおりに実行されます。ダイアログが非常に煩わしくなります。ダイアログがアクティブで、別のウィンドウから何かをコピーして貼り付けることができないことを嫌わない人がいるでしょうか。しかし、それは代償です。

これは、コード内で DoEvents を安全に使用するのに必要なことです。すべてのフォームの Enabled プロパティを false に設定すると、問題をすばやく効率的に回避できます。もちろん、実際にこれを好むプログラマーはいません。実際にそうしません。これが、DoEvents() を使用すべきでない理由です。スレッドを使用する必要があります。スレッドは、カラフルで不可解な方法で足を撃つための完全な武器庫を提供しますが、自分の足だけを撃つという利点があります。通常、ユーザーが自分の足を撃つことはできません。

C# と VB.NET の次のバージョンでは、新しい await および async キーワードによって異なる武器が提供されます。これは、DoEvents とスレッドによって発生する問題に少し影響を受けましたが、主に、ファイルからの読み取りのように、非同期操作の実行中に UI を更新し続ける必要があるWinRT の API 設計に影響を受けています。

おすすめ記事