You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WritePixels在Timer Tick事件中无法更新WriteableBitmap求助

解决WriteableBitmap在Timer Tick事件中无法更新的问题

核心问题分析

你的代码在Timer外部正常但Tick事件内失效,大概率是线程调度或UI更新逻辑的问题,以下是针对性的解决方案:


1. 替换Timer类型为DispatcherTimer

WPF的UI元素只能在Dispatcher(UI线程)中更新,如果使用System.Timers.Timer,其Tick事件会在后台线程触发,直接操作WriteableBitmap可能导致UI无法感知变化。换成DispatcherTimer确保事件在UI线程执行:

// 初始化时改用DispatcherTimer
private DispatcherTimer timer = new DispatcherTimer();

// 在构造函数或初始化方法中设置
timer.Interval = TimeSpan.FromMilliseconds(1); // 按需调整刷新间隔
timer.Tick += Timer_Tick;
timer.Start();

2. 避免重复设置Source

全局的targetBitmap只需在初始化时绑定一次到targetControl.Source,无需每次Tick都重复赋值。重复设置相同引用会让UI跳过重绘逻辑:

// 初始化时执行一次即可
targetControl.Source = targetBitmap;

3. 修正像素索引与边界判断

你的边界判断pixelIndex >= 100 * 100 * 4错误:100×100的图像总像素数是10000,pixelIndex是按像素计数的,应该判断是否超过总像素数;同时要正确计算字节数组的起始索引,避免每次写入整个数组:

private void Timer_Tick(object sender, EventArgs e)
{
    // 边界判断:总像素数为100*100,而非字节数
    if (pixelIndex >= 100 * 100)
    {
        timer.Stop();
        return;
    }

    int x = pixelIndex % 100;
    int y = pixelIndex / 100;
    // 计算当前像素在字节数组中的起始位置
    int byteStartIndex = y * stride + x * 4;

    Int32Rect rect = new Int32Rect(x, y, 1, 1);            
    // 仅写入当前像素的4个字节数据
    targetBitmap.WritePixels(rect, pixels1d, stride, byteStartIndex);

    pixelIndex++;
}

4. 可选:手动触发重绘

如果上述调整后仍不生效,可在WritePixels后添加手动刷新逻辑:

targetBitmap.Invalidate();

额外排查点

  • 确认WriteableBitmap的PixelFormat与pixels1d的字节格式匹配(比如Bgra32对应每个像素4字节,顺序为蓝、绿、红、Alpha)
  • 检查stride计算是否正确:stride = targetBitmap.PixelWidth * (targetBitmap.Format.BitsPerPixel / 8)

内容的提问来源于stack exchange,提问作者TomQ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 10:05:11