1

さて、これは本当のヘッドスクラッチャーです:

ウィンドウ全体 (writeableBitmap) を構成する画像にいくつかのピクセルが描画されるようにするメニュー項目を選択すると、それが行われ、正しく表示されます。

ただし、while ループ (たとえば 5 つのループ) を同じメソッドに追加すると、ループが完了するまでビットマップ上の描画は表示されず、5 番目に再描画されたビットマップが正しく表示されます。

では、メニュー項目が選択されているが while ループでスキップされているときにウィンドウに発生している「自動更新」のようなものはありますか?

詳細。これは問題なく動作します (「きれいな」画像を取り込み、その上に何かを描画し、表示します):

// This brings in a 'clean' image
writeableBitmap = new WriteableBitmap(CleanVegMap);
image.Source = writeableBitmap;
// This makes a bunch of draws on the bitmap
DrawDinos2d();

ただし、これは 10 秒間「消えて」、最後 (つまり 5 番目) の画像のみを表示します。

int z = 0;
while (z < 5){
z++;
   // This brings in a 'clean' image
   writeableBitmap = new WriteableBitmap(CleanVegMap);
   image.Source = writeableBitmap;
   // This makes a bunch of draws on the bitmap
   DrawDinos2d();
}

新しいアイデア: 5 つの「描画された」writeableBitmaps が何らかの形でシステムによってメモリにキャッシュされている可能性はありますか?

Dispatcher を使用してみました (以下のように):

                Dispatcher.Invoke((Action)delegate
            {               
                writeableBitmap = new WriteableBitmap(CleanVegMap);
                image.Source = writeableBitmap;
                DrawDinos2d();
            });

同じこと (10 秒間消えてから、最後の画像のみを表示します。

別の手がかり: MessageBox を各ループの一番下のループに入れただけで、どういうわけか疑ったように、再描画された画面が正しく「ブリット」されました。何とかして:

 System.Windows.MessageBox.Show("Glarp!");

この呼び出しにより、システムが「起動」しました。繰り返しますが、何かアイデアはありますか?

4

1 に答える 1

1

MessageBox を処理に挿入し、期待どおりの結果が得られたときに発生したのは、MessageBox が開いている間に UI スレッドが「追いつく」可能性があったことです。そのため、MessageBox を使用すると突然機能するという「幻想」が作成されましたが、舞台裏では、スレッドが自分自身を整理して命令キューをクリアしているだけでした。

プログラムで同じ効果を作成するには、次のような方法でビットマップを更新できます (ETA: .NET 4.5 Framework が必要です)...

    public void UpdateBitmap()
    {
        WriteableBitmap writeableBitmap = new WriteableBitmap
                                (100, 100, 96, 96, PixelFormats.Bgr32, null);
        writeableBitmap.Dispatcher.InvokeAsync(() =>
            {
                Console.WriteLine("work goes here");
            });
    }

これにより、ビットマップのディスパッチャーが関連付けられているスレッドで操作が非同期的に実行され、UI が追いつく機会が与えられます。「DrawDinos2d」メソッドのペイロードによっては、処理をバックグラウンド スレッドに移行し、1 つずつ UI スレッドにフィードする必要がある場合がありますしかし、まずはこのアプローチから始めてください。

ETA: .NET 4.0 フレームワークでは、上記に対応するものは次のようになります...

    public void UpdateBitmap()
    {
        object[] objs = new object[] {null};
        WriteableBitmap writeableBitmap = new WriteableBitmap(
             100, 100, 96, 96, PixelFormats.Bgr32, null);
        writeableBitmap.Dispatcher.BeginInvoke((SendOrPostCallback)delegate
            {
                Console.WriteLine(@"work goes here");
            }, objs);
    }

ドキュメントは、「 System.Windows.Threading.Dispatcher が作成されたスレッドで、指定された引数を使用して、指定されたデリゲートを非同期的に実行します。

于 2013-07-18T23:56:34.650 に答える