Jump to content
Shrinavat

Strange TWICImage behavior when working in a thread.

Recommended Posts

Here is the simplest code:



unit Unit1;

interface

uses
  System.SysUtils,
  System.Classes,
  Vcl.Graphics,
  Vcl.Imaging.jpeg,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.StdCtrls,
  OtlParallel,
  OtlTask;

type
  TForm1 = class(TForm)
    btnReadInOTL: TButton;
    btnReadInGUI: TButton;
    procedure btnReadInGUIClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btnReadInOTLClick(Sender: TObject);
  private
    FMS: TMemoryStream;
    FTestWorker: IOmniBackgroundWorker;
    procedure Asy_Test(const workItem: IOmniWorkItem);
    procedure HandleRequestDone(const Sender: IOmniBackgroundWorker; const
        workItem: IOmniWorkItem);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  FMS := TMemoryStream.Create;
  FMS.LoadFromFile('test.jpg');

  FTestWorker := Parallel.BackgroundWorker
    .Execute(Asy_Test)
    .OnRequestDone(HandleRequestDone);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FMS.Free;
  FTestWorker.CancelAll;
  FTestWorker.Terminate(INFINITE);
  FTestWorker := nil;
end;


procedure TForm1.Asy_Test(const workItem: IOmniWorkItem);
var
  wic: TWICImage;
  jpg: TJPEGImage;
  bs: TBytesStream;
begin
  bs := TBytesStream.Create;
  try
    bs.Write(FMS.Memory^, FMS.Size);
    bs.Position := 0;
    wic := TWICImage.Create;
//    jpg := TJPEGImage.Create;
    try
      wic.LoadFromStream(bs);
//      jpg.LoadFromStream(bs);
//      jpg.SaveToFile('TJPEGImage.jpg');
    finally
      FreeAndNil(wic);
//      FreeAndNil(jpg);
    end;
  finally
    FreeAndNil(bs);
  end;
end;

procedure TForm1.HandleRequestDone(const Sender: IOmniBackgroundWorker; const
    workItem: IOmniWorkItem);
begin
  if workItem.IsExceptional then
    Application.MessageBox(PChar(workItem.FatalException.Message), '')
end;

procedure TForm1.btnReadInGUIClick(Sender: TObject);
var
  wic: TWICImage;
  bs: TBytesStream;
begin
  bs := TBytesStream.Create;
  try
    bs.Write(FMS.Memory^, FMS.Size);
    bs.Position := 0;
    wic := TWICImage.Create;
    try
      wic.LoadFromStream(bs);
      Application.MessageBox('All is OK', '');
    finally
      FreeAndNil(wic);
    end;
  finally
    FreeAndNil(bs);
  end;
end;

procedure TForm1.btnReadInOTLClick(Sender: TObject);
begin
  FTestWorker.Schedule(FTestWorker.CreateWorkItem(0));
end;

end.

When I click on the button "Read Image in GUI Thread", then everything is fine. TWICImage loads the image from the stream.

However, the same code does not work in the thread (click on the button "Read Image in OTL Thread"), I get AV "Access violation at address 0050316F in module 'Project1.exe'. Read of address 00000000".

If you use TJPEGImage instead of TWICImage, then everything works fine in both cases.

I don't get what the problem is. Can someone explain to me in simple terms what should I do in order for TWICImage to work in the thread? I want to use TWICImage because it allows you to download a wide variety of image formats, not just jpeg.

 

Delphi 10.2.3, Win7SP1 x64. Project full source is in attachment

 

test_OTL_read_from_memory.zip

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×