I am still a bit of a novice when it comes to the PPL. I want to run a background process where I can send an indy email in the background, so that sending 100's of the little blighters doesn't lock up the UI.

I am still a bit of a novice when it comes to the PPL. I want to run a background process where I can send an indy email in the background, so that sending 100's of the little blighters doesn't lock up the UI.

I have tried many variations, including good old fashioned threads, but was not getting too far with that one, as I had a bunch of memory leaks !

So I decided to give PPL a go and have tried wrapping my code with either:

TTask.Run(
procedure
begin
end );

Or

var
SendResult: IFuture ;

begin
SendResult := TTask.Future( function: TSendResult
begin
end );

the problem I have is that I want to pass into either of these the msg, which contains all the data about the email ( from, to, recipients, attachments .... )

but msg is always nil'led or set to default values when I step into the code inside, which I think from what I understand would be correct .... but I need this data.

Does anyone know how I pass a variable into a parallel method/section

Thanks


Comments

  1. I think that issue has been discussed a couple days ago. If your data is nil then that is because you don't capture it properly. You might consider a queue to put your email data into and a worker thread that works the queue and processes them.

    ReplyDelete
  2. Stefan Glienke Not so sure I'm following you on that one .... I hav'nt got a clue how to setup a queue and a worker thread. Do you have the link to this original post from a few days ago ?

    BTW; the contents of msg is fine just before I step into the PPL. Once inside the parallel section the values inside msg are nil or zero'd and I am not doing anything to msg between those points.

    ReplyDelete
  3. That will be because there is something wrong with your code. But we can't see it. Possible cause is that you declared the variable in two separate places rather than using a capture, but that's a guess. Probably I should not even be guessing.

    ReplyDelete
  4. David Heffernan So, I have a question for clarification:

    Q: If I have a procedure that has a PPL section inside it ( such as TTask.Run .. ). If that procedure has a parameter ( msg: TuexSMTPMessage ); then in your opinion should the Parallel section within the procedure have access to the variable msg?

    ReplyDelete
  5. It's hard understand the scenario if you won't show code and try to describe instead. Another possible problem is that there is only one variable that is captured by, and shared by all tasks. Again, it's probably a waste of time to expect us to guess.

    ReplyDelete
  6. David Heffernan As ever you are right !! As my code was firing in Parallel; I was forgetting about the whole parallel thing ( dooooh ) and I was killing of the TObjectList<> holding the msg instances, but naturally as this was all in parallel it was happening before it could be used.... Fab

    So, I have another question ... how do I know when these parallel's are finished.... I see there is a WaitFor, but that applies to an array of ITask ( which I suppose I could do )

    ReplyDelete
  7. You don't to wait. That puts you back where you started. You need to subscribe to a completed event, but I don't know the details for this library. I've never trusted it after its bug ridden birth.

    ReplyDelete
  8. David Heffernan That makes sense ! Thanks ! "bug ridden birth" .... Don't you use the PPL then ?

    ReplyDelete
  9. Understand multithreading first. PPL is not a silver bullet (regardless its arguable quality). Understand that you need to keep a resource being used by some asynchronous task around at least as long as that task needs to finish whatever it is doing with that resource. What you describe is being done with a producer consumer pattern where both sides can have 1-n. In the middle you have a thread safe queue where the producers (those that want to send emails) enqueue them and on the other side you have the consumers (like some worker thread) dequeueing items and processing them (sending away the email).

    ReplyDelete
  10. Stefan Glienke Still not following you ! You obviously have far more experience of this kind of coding ! This is only my second venture into PPL and although I have used TThread's quite a bit in the past; they tended to be in isolation, in that they performed a task in isolation with a modicum of settings. Generally, I believe it would be refereed to as a Factory pattern.

    I have never needed ( until now ) to keep a resource from being used by some asynchronous task ....

    So I havn't got a clue how to protect what I have inside my TTask from being overwritten by the next call

    Any pointers to documentation where I can read a bit more about how to resolve this would be very gratefully received

    ReplyDelete
  11. Tony Danby It's not different from using regular threads, in that you need to be careful who manipulates what when.

    For this, I think I'd just go with a regular TThread. Then you have full control.

    ReplyDelete
  12. In your anonymous function add a variable as a parameter that will hold your message data that should be used in function body.
    When calling future task pass the message value in that parameter.
    Did not try that but should work.

    ReplyDelete
  13. R Gosp Tend to agree with you after reading large chunks of documentation on how this kind of thing can be done .... i only need to pass in one variable anyhow, so that's good ... everything else is created and destroyed on the fly

    ReplyDelete
  14. Attila Kovacs Yes, I wouldn't disagree with you, but in our case we are only sending emails as rapidly as we can in a threaded fashion in order to stop the UI from hanging .... that architecture would be overkill for us and my boss would hang me by my d*ck for even suggesting it ;-)

    ReplyDelete
  15. Attila Kovacs I used to have in main form onClose event a Sleep timer while there are not terminated threads

    ReplyDelete
  16. Tony Danby You probably have this part sorted, but I used the following link (2nd last code section, stripping out the TLS stuff) to create a Windows app to send out our small number of emails (~100)

    lastaddress.net - Sending email with attachments using Delphi, Indy 10.5.5 and GMail

    ReplyDelete
  17. Tony Danby Modeled off that code, I am using this ...

    drive.google.com - drive.google.com/open?id=0BzSEgxJLWoeHQ0kzM2RGMnpOcEE

    I wanted to tick rows of customer data as it goes, so it updates an array with success status. It retries sending 3 times (I think) if unsuccessful. I keep an array of 4 Tasks, and feed email jobs in as they complete. This was what worked best with our internet provider. YMMV.

    The email body is passed as a TStringList to the procedure, and freed by the Task when it is done.

    This works perfectly for me in VCL/Windows, but judging from Malcolm Groves' post about threads on Android (linked above by Gustav Schubert), it might have issues there. I now understand how to fix that issue with a closure, but seems not to be necessary in my environment at the moment.

    ReplyDelete
  18. Paul McGee I read the code-partners.com - Parallel (mis)Adventures – Code Partners link posted on here right through very interesting article. so now what I do is create a single object holding all the objects I need ( these objects are assigned, not by reference ) and are then enqueued and dequeued as described in the article. In my case I only needed IdSMTP as I was connecting and disconnecting at various points in my PPL and this object needed to be "safe" from writing over the top of the next one etc ...
    At the end of the PPL section I get rid of the copied instance of IdSMTP

    It all works perfectly and like a bullet. It goes out of sequence, but that is not an issue for me as we are trying to send as many emails as possible.

    It's all been tested for leaks and it's fine.

    I have learned several things about PPL from wise people in this post and I want to thank everyone who helped me

    ReplyDelete

Post a Comment