Adz Baywes 0 Posted September 19, 2021 I am currently converting some C# code to Delphi and came across some methods that I am not sure on how to properly translate. The C# goes like this: public class Test { public string TestMe { get; set; } public string Category(string cat) { ... } } ... public class DoTest { public async Task<Test> Meth(string message) { return await Category(message); } } The async Task<T> Meth() function is where I'm lost type TTest = class private FTestMe: string; FCategory: string; public function TestMe: string read FTestMe write FTestMe function Category: string read FCategory write FCategory end; ... type TDoTest = class public function Meth(AMessage: string): Test end; implementation function TDoTest.Meth(AMessage: string): Test var MyTask: ITask; begin MyTask := TTask.Create( procedure begin ... end ); MyTask.Start; end; Can this be done with PPL and is my declaration/implementation of the function even correct? Share this post Link to post
Vincent Parrett 765 Posted September 20, 2021 (edited) There isn't really a 1 for 1 conversion here - the Delphi language/ppl does not have any async/await constructs . So because of that your translation isn't correct. That said, your c# example isn't valid either. Your TDoTest.Meth doesn't actually return anything so that's a problem there. So you are left with a few options. Deal with it yourself. which as you have found is not easy (even with the PPL) - or find another library that could handle it. If you are doing this for windows only, OmniThreadLibrary is an option but has a fairly steep learning curve (worth it if you need to do complex threading stuff). For simple code, I wrote a wrapper over Omni (VSoft.Awaitable) which provides a poor mans version of async/await (omni does have this too, but it's missing a few features like cancellation and returning values). function TDoTest.Meth(AMessage: string): IAwaitable<Test> begin //configure our async call and return the IAwaitable<string> result := TAsync.Configure<Test>( function(const cancelToken : ICancellationToken) : Test begin //.... do some long running thing result := TTest.Create end, token); end; //calling code procedure TAnotherClass.DoSomething; var doTest : TDoTest; begin doTest : TDoTest.Create; //this will not block. doTest.Meth('the message', FTokenSource.Token) // optional .OnException( procedure (const e : Exception) begin //handle the exception - runs in calling thread end) // optional .OnCancellation( procedure begin // call was cancelled - do any cleanup here // runs in calling thread end) // required, the call to Await actually fires off the task .Await( procedure (const value : TTest) begin //runs in the calling thread. Label1.Caption := value.TestMe; end); end; The FTokenSource above is an ICancellationTokenSource - VSoft.Awaitable depends on VSoft.CancellationToken - in VSoftAwaitable it maps over Omnithread's cancellation token - delphi doesn't have one in the rtl or PPL (a glaring omission imho). It's hard to give a definative example with the invalid c# example though. BTW, to understand what async/await actually does in C#, this page sums it up quite nicely. Edited September 20, 2021 by Vincent Parrett typo Share this post Link to post
Adz Baywes 0 Posted September 20, 2021 Hi Vincent, thanks for taking the time answering my inquiry. I was also looking at your CancellationToken yesterday as it may be needed on my project, the C# code does use it. The example and explanation you have provided is sufficient for now. I will have to do some more research and read up on the link you have provided. Will be posting if anything comes up. Thanks again! Share this post Link to post