在线程里用Bitmap载入图片,并在PaintBox上画出来。
开始的时候可以正常显示,但运行一会儿后PaintBox就不更新了。当拖动滚动条(PaintBox大于窗口),或者放大缩小(PaintBox跟随变化),甚至什么都不动有时候也会出现这样的状况。
在线程里设断点可知线程仍在正常运行,载入的图片也是正确的。代码大至如下:
procedure TFrameThread.Execute;
begin
  while not Terminated do
  begin
    Inc(i);
    FBitmap.LoadFromFile(IntToStr(i) + '.bmp');
    with Form1.PaintBox1 do
    try
      Canvas.Lock;
      Canvas.StretchDraw(Rect(0, 0, Width, Height), FBitmap);
    finally
      Canvas.Unlock;
    end;
    Sleep(100);
  end;
end;

解决方案 »

  1.   

    用sleep不是很好吧,用SetWaitableTimer吧
      

  2.   

    没那么复杂吧,Sleep有什么不好?就是挂起线程。
      

  3.   

    一般不这样写, 一般是下面那种写法:procedure TMyThread.Execute;
    begin
      FreeOnTerminate := True;
      Synchronize(dosomething);
    end;procedure TMyThread.dosomething;
    begin
        Inc(i);
        FBitmap.LoadFromFile(IntToStr(i) + '.bmp');
        ...
    end;
      

  4.   

    如果能用Synchronize的话就不是问题了要的是多线程显示,否则主线程被拖慢。
      

  5.   

        try
          Canvas.Lock;
          Canvas.StretchDraw(Rect(0, 0, Width, Height), FBitmap);
        finally
          Canvas.Unlock;
          sleep(0);      // <- 加个进去试试
        end;
        Sleep(100);
      

  6.   

    始终觉得用SetWaitableTimer来处理较好
      

  7.   

    Canvas.StretchDraw(Rect(0, 0, Width, Height), FBitmap);
    后边加个 Invalidate 刷新试下
      

  8.   

    加的那句是什么意思呢?如果Unlock有问题的话加什么都一样吧?待测试
      

  9.   

    需要使用线程同步,因为你多个线程在同时操作PainBox
    可以利用Synchronize
    也可以使用临界区
      

  10.   


    如果多个线程100ms刷新一幅图,是可能有些图没看到就被覆盖了感觉多线程提供图片文件名,覆盖到一个string;主线程用定时器取这个变量来刷新
    比较好
      

  11.   

    一个image,先加载图片a,再加载图片b,就是b把a覆盖了
    如果刷新慢、卡,那用户只会看到b,没机会看到a曾经显示过
    所以,不如直接用a、b的文件名来更新,定时器来真正显示不过,如果你只有一个工作线程,而且有100ms的显示时间,应该不会看不到a的
    正因为定时器不是多线程,所以,显示图片这样容易与主线程冲突的工作,由定时器做更保险
    工作线程不用涉及图片加载,只负责告诉主线程的定时器,现在该加载什么文件
    定时器判断目前需要加载的图片文件名是不是已经就绪,是则加载之并把文件名变量清空,否则什么也不干
    这样,定时器的间隔可以设的很短,如10ms
      

  12.   

    在主线程的 定时事件 里显示
    定时事件:
    begin
      timer1.enabled:=false;
      if imgfilename<>'' then
      begin
        FBitmap.LoadFromFile(IntToStr(i) + '.bmp');
        with Form1.PaintBox1 do
          Canvas.StretchDraw(Rect(0, 0, Width, Height), FBitmap);
        imgfilename:='';
      end;    
      timer1.enabled:=true;
    end;线程:
    procedure TFrameThread.Execute;
    begin
      while not Terminated do
      begin
        Inc(i);
        imgfilename:=IntToStr(i) + '.bmp';
        Sleep(100);
      end;
    end;
      

  13.   

    不过,这个交互的焦点:imgfilename的读写,可能需要加一个互斥保护
      

  14.   

    要在主线程里显示也要把LoadFromFile放在子线程里,我实际的代码里LoadFromFile是在另一个线程里,这个子线程只是负责收到载入图片的消息后显示。
    程序这二天没有出错,暂时不改了。哪位有兴趣讨论一下:所有的代码都执行了,为什么会不显示呢?Windows在什么情况下会不刷新窗口?主程没有不响应,只是PaintBox不刷新。
      

  15.   

    工作线程不会影响到主线程的,只是显示的时候会有一点点影响吧,占CPU 5%不到。
      

  16.   

    试验了一下,循环加载、显示4幅1.9M的bmp(1600x1200x256色),cpu占用保持在16%,如果最小化,则会降到0如果加载慢,显示快,可以在工作线程里加载,定时器仅仅做显示
    只是试验。
    你的代码已经写好,而且作为一个通用的准视频播放,使用主线程的定时器,不如线程、函数来的方便