VCL对多线程的支持不行;

解决方案 »

  1.   

    建议你不要一点一点读,
    可以一行一行读就快多了;Provides indexed access to each line of pixels.
    __property void * TBitmap::ScanLine[int Row] = {read=GetScanline};
    Description
    ScanLine is used only with DIBs (Device Independent Bitmaps) for image editing tools that do low-level pixel work.
      

  2.   

    Bitmap1.ScanLine[每一行号];
    就是每行象点的首址;
      

  3.   

    什么是scanline??我好想没听说过嘛..??
    我的程序在有些象素点要把它的色彩值设为它走围4点(上下左右4点)的平均值,这样也能用scanline吗?
      

  4.   

    我现在组要的问题不是在读取pixel上,而是在写入时好象发生了数据丢失,这是怎么会事?
      

  5.   

    肯定不是delphi的错误,多喳喳你的程序!
      

  6.   

    多线程中会同时操作Bitmap1,这是VCL所不允许的;
      

  7.   

    多线程中会同时操作Bitmap1,这是VCL所不允许的;
    但可改成API函数操作的办法试试。
      

  8.   

        编一编多线程的程序可以加深对多线程的了解;
        我认为:
        如果各个线程之间空闲时间不多,采用多线程的办法不一定能
    加快速度,由于VCL限制多线程访问,不得不用“同步”、“互斥”
    的办法减少冲突,进一步降低了多线程的效率;
       我的看法不知对不对?!
      
      

  9.   

    我同意BCB([email protected])。
    VCL原来的结构的确实不支持多线程,但后来它用了一个巧妙的方法实现了对多线程的支持。而且其实现的结果是,使用它的程序员在用VCL编写多线程程序时较少的使用烦琐的“同步”、“互斥”,当然VCL的原码并不阻止你的进一步研究。
      

  10.   

    在多线程,改成“同步”方式访问Bitmap1试试应该没问题了(请试一试),
    可大队人马排队通过独木桥,有了独木桥哪还能快? 
      

  11.   

    什么是同步模式???我的问题用一个简单的例子来说明:
    procedure ConvertThread.Execute;
    var
      i,j:integer;
    begin
      for j:=0 to Form1.Image1.Height do begin
        for i:=0 to Form1.Image1.Width do begin
          form1.Image2.Canvas.Pixels[i,j]:=form1.Image1.Canvas.Pixels[i,j];
        end;
      end;
    end;
    这是一个线程的execute中的内容,请各位试试,我运行的时候确实是有些点被绘成白色的空值了,
    如果要设成同步模式,那该怎么设呢??对不起,我只有这点分了,请帮帮忙吧
      

  12.   

    正如楼上几位所说,因为性能的原因,VCL不直接支持线程,或者说是线程不安全的。
    但是,可以用TThread.Synchronize来同步线程对VCL的操作。
    请看下面的例子,具体请看Delphi中TThread的帮助。This example shows how to call a button抯 click method in a thread-safe manner:procedure TMyThread.PushTheButton;begin
      Button1.Click();
    end;procedure TMyThread.Execute;
    begin
    ...
      Synchronize(PushTheButton);
      ...
    end;所以,比照这个例子,你应该把画图函数独立成一个过程,然后在ConvertThread.Execute中通过Synchronize来调用。
    还有,提示一下,如果你一点点甚至是一条条画图的话,速度是很慢的。建议在内存中开辟一个bitmap,画上去,然后整个复制到界面上。这样快非常之多!
      

  13.   

    我用Synchronize的方法确实可行了,不再有数据丢失的现象,可是我发现它的速度几乎和不做在线程里的一样,那样的话我不是就没有必要做成多线程的了吗?但还是很感激一上给予帮助的各位大哥们!!很抱歉,我分不够,平分后只有一点点了。。
      

  14.   

    我用Synchronize的方法确实可行了,不再有数据丢失的现象,可是我发现它的速度几乎和不做在线程里的一样,那样的话我不是就没有必要做成多线程的了吗?但还是很感激一上给予帮助的各位大哥们!!很抱歉,我分不够,平分后只有一点点了。。
      

  15.   

    Sychronize的方法其实是样该过程回到主线程下执行,那速度当然和没写到线程里面一样啦。
    你试一下把循环写到excute里面把描点的过程写到sychronize里面再试一下。因该就可以了。
      

  16.   

    procedure ConvertThread.Execute;
    var
      i,j:integer;
    begin
      for j:=0 to Form1.Image1.Height do begin
        for i:=0 to Form1.Image1.Width do begin
       Synchronize(drawBitmap);
       end;
      end;
    end;
    procedure TMyThread.drawBitmap();begin
          form1.Image2.Canvas.Pixels[i,j]:=form1.Image1.Canvas.Pixels[i,j];
    end;
      

  17.   

    关于速度的问题:
    首先,如果你的硬件(2cpu?)和操作系统(WinNT? 2000?)不是真正支持多处理器,那么,多线程整体上只会降低速度,而不会提升速度。最多,可能操作性,相应性能好一点。
    对于你的程序,要提高速度,最有效的方法,是在内存中画好之后,整体复制到界面控件上。
      

  18.   

    真不好意思。。又遇到问题了。。Synchronize的参数好想必须是不带参数的函数,如果我写成:procedure mythread.Execute;
    var
      i,j:integer;
    begin
      for j:=0 to Form1.Image1.Height do begin
        for i:=0 to Form1.Image1.Width do begin
          Synchronize(drawBitmap(i,j));//这里会出错!!!!!!!!!!
        end;
      end;
    end;procedure mythread.drawBitmap(x,y:integer);
    begin
      form1.Image2.Canvas.Pixels[x,y]:=form1.Image1.Canvas.Pixels[x,y];
    end;这样还是不对,那我该怎么办呢。。??
      

  19.   

    不使用多线程的方法我也试了,自己生成两个tbitmap类,然后对图片进行处理,再保存会timage,那样趋势很快,但我希望我的能够不段看到程序执行的状况,就是说能看到当前把图片处理到哪里了,所以那样做不太合适,
    因此剩下的反感只有两种:
    1)直接在当前form中对图片进行处理,但那样必须加上application。processmessages语句,速度实在太慢
    2)用多线程的方法。。
    所以我想我使用多线程的方法还是没错的吧
      

  20.   

    在多线程中处理本来就麻烦,弄得不好是会不稳定的,最好不要用TBITMAP类嘛,或者用LOCK把CANVAS锁住可能也可以.
      

  21.   

    总算可以了,只要在线程里操作图片前同时对两张图片的canvas调用lock,完成后再用unlock 就可以了。。
    但我还是不太清楚为什么要这样做,是因为timage在自动重绘时不能读取其中的数据吗?还忘能有人告诉我。。
     
    非常感谢 Raptor,,我怎么给你分呢??
      

  22.   

    总算可以了,只要在线程里操作图片前同时对两张图片的canvas调用lock,完成后再用unlock 就可以了。。
    但我还是不太清楚为什么要这样做,是因为timage在自动重绘时不能读取其中的数据吗?还忘能有人告诉我。。
     
    非常感谢 Raptor,,我怎么给你分呢??