1

好的,这是一个真正令人头疼的问题:

如果我选择一个导致图像的菜单项,它构成了整个窗口(一个 writeableBitmap)以在其上绘制一些像素,它会这样做并正确显示。

但是,如果我在相同的方法中添加一个 while 循环(比如说 5 个循环),则位图上的绘图在循环完成之前不会显示,然后正确显示第 5 个重绘位图。

So, is there some sort of 'automatic refresh' that is happening to the window when a menuitem is selected but is being skipped in the while loop?

更多细节。这很好用(带来一个“干净”的图像,在上面画一些东西,显示它):

// 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 插入处理并获得您期望的结果时发生的情况是 UI 线程有机会在 MessageBox 打开时被“赶上”。因此,它产生了一种“幻觉”,即使用 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”方法的有效负载,您可能必须将处理迁移到后台线程并逐个将其提供给 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 回答