Shrinavat 16 Posted February 6, 2019 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
Sherlock 663 Posted February 6, 2019 You may have to CoInitialize and CoUninitialize when multi threading and using COM objects. 1 Share this post Link to post
Shrinavat 16 Posted February 6, 2019 Ooops! I completely forgot about that... Thanks! Share this post Link to post