-2

Hello i'm having some issues making my class threaded. I'm following a tutorial and this guy says we have to inherit from TThread and then override Execute. That's cool but only overriding is not enough for me i need to overload it and add some arguments. I have a rest service that i want to make threaded so my idea was to make the getCommand of the idhttpServer on a thread. Therefore i wanted to add the Context, Request and Response as arguments of the command get. That's the code:

MyRest = class(TThread)
...some methods...
protected
  procedure Execute(AContext: TIdContext;
      ARequestInfo : TIdHTTPRequestInfo; AResponseInfo:TIdHTTPResponseInfo);overload; override;
end;

And then on my create i want to do this basicly:

  FServer.OnCommandGet :=  Execute;

FServer is the TIdHttpServer.

The problem is that delphi cries already when defining the execute procedure. It says Execute differs from previous declaration... this ... Of course it differs that's why i said overload. Any Ideas how i can do this?

John
  • 261
  • 2
  • 16
  • If you wanted to use `TThread` which is quite unusual by itself as that's what Indy manages for you, do not name the method `Execute` and remove those `overload` and `override` directives. – Victoria Feb 23 '18 at 09:59
  • 2
    Looks to me like you need to scrap the `TThread` tutorial you're using, and look for a `TIdHTTPServer` tutorial instead. Yes, it uses threads by itself already. No, it does not require you to write a `TThread`. – Jerry Dodge Feb 23 '18 at 12:14
  • Aha, so it became yes or no question with no edit so far. Well, I have an idea what to do.. Drop this code. – Victoria Feb 23 '18 at 14:07
  • @Victoria Didn't mean to twist it to yes or no. Just attempting to read OP's mind and answer their real questions. – Jerry Dodge Feb 25 '18 at 01:42
  • @JerryDodge I want to use TThread on my Class not on IdHttpServer. To test if IdHttpServer is threaded i created gui using the class currently not threaded that uses tIdHttpServer as one of their fields. I then did a lot of requests at once and the gui just froze. That's not threaded at all. – John Feb 26 '18 at 09:48

1 Answers1

4

You can't change the arguments. The Execute function is called by the lower level framework and that determines, once and for all, the signature of Execute.

What you can do is add some fields to your thread class to contain the extra information.

  1. Add three fields to your MyRest class, one for each of your parameters.
  2. Define a constructor for your MyRest class that accepts these three parameters.
  3. In the body of that constructor, make a note of the passed parameters in your fields.
  4. In your Execute function, read those fields.
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Note that I am simply answering the question as asked. Whether or not you should to be implementing threading manually I cannot say. – David Heffernan Feb 23 '18 at 09:52
  • Thos fields are set by the idhttpserver when a request is made on server side. I can't set them once on create of MyRest. If i set them on create they will alway be empty. – John Feb 23 '18 at 09:52
  • What do you mean "implement the thread manually"? I really have no idea how Threading work in delphi i'm following a tutorial. I did some multithreding in c# but in delphi it just looks strange. Everyone says override execute when i search for threading in delphi – John Feb 23 '18 at 09:53
  • I have no idea what problem you are actually solving. But I know that there are facilities in Indy that take care of threading for you. I'm suggesting that perhaps you should be letting Indy manage threading. But I don't know because you didn't describe your root problem. I just answered the question you asked. – David Heffernan Feb 23 '18 at 09:55
  • As far as your first comment above goes, if you believe that you know these parameters at the point in time where `Execute` is know, then you can know them when you create the thread. Your comment makes little sense and suggests that, as you yourself state, that you have no idea how threading works. Which means that while this is the answer to the question you asked, your problems are somewhat deeper. – David Heffernan Feb 23 '18 at 09:56
  • I want to make my Rest layer be on a different thread so when someone uses my rest it won't freeze the gui or what ever else they are doing. Right now i made a gui that does nothing actually but if i make some massive calls to my rest i can't move the gui anymore until the requests are done. So that's my problem. I've searched for thread and there i am. Using tThread. I can't make Execute without parameters work in my case that's why i wanted to overload it. Execute alone won't be of any use, i don't anything to process, the whole rest should be on a different thread – John Feb 23 '18 at 09:58
  • As I explained, if your parameters are known when the thread starts, i.e. when `Execute` is called, then they can be known when you instantiate the thread instance. Which is why my answer is correct. However, if you want a background thread running constantly, or perhaps a pool of such threads, then that would require a different solution, but it's not what was asked in the question. – David Heffernan Feb 23 '18 at 10:01
  • They are not known when you call Execute. They are known only when someone makes a request. That's why i wanted to set the oncommandGet of the idhttpserver to execute of the thread so when a request is made it sets the parameters of the execute. But since i can't do that i have no idea how to make my whole classes threaded. I have no use of execute. – John Feb 23 '18 at 10:03
  • 5
    @John, Indy uses own thread pool. You're just not supposet to do what you're doing. `TIdHTTPServer` is already multithreaded. – Victoria Feb 23 '18 at 10:44
  • @Victoria Hum ok, any idea how i can separate my gui from my server then? – John Feb 23 '18 at 10:48
  • 1
    Event methods assigned to events like `OnCommandGet` are executed by the connection thread; they are running in the context of a thread different from main. So without some synchronization mechanism you must not access UI from there. Better throw that tutorial away and start thinking about major `TIdHTTPServer` events (not all of them) as those _"running as a worker thread"_. – Victoria Feb 23 '18 at 10:54
  • @john According to the question, they must be known when `Execute` is called, because that's what you wrote! – David Heffernan Feb 23 '18 at 11:08
  • @DavidHeffernan Why do you assume that my question is correct? I don't know if i should do it like that that's how i was planning to do. If i were able to do it like that the execute would have been called on every request and the params are only known at that moment. Not when icreate the actual object... – John Feb 23 '18 at 11:28
  • @John, you're not doing it correctly. You're not supposed to create a thread. If you want to have a custom object that will remain alive since the client connection, during the communication until it disconnects, you can derive it from `TIdServerContext` and it will get passed as the context parameter in the events that are executed in a worker thread context (thread, which is taken from thread pool). – Victoria Feb 23 '18 at 11:42
  • 2
    But @John, you've asked about a specific problem, and that's been answered. If you needed help about how to design a custom object that will be created for each client, ask about that in a separate question, please. – Victoria Feb 23 '18 at 11:49
  • 1
    *Why do you assume that my question is correct?* Because that's pretty much the essence of Stack Overflow. People ask questions. People answer those questions. You can't expect, not here at least, to ask one question and receive the answer to a different question. The articles in the [help] may prove useful. I'm confident I answered the question you asked. – David Heffernan Feb 23 '18 at 12:12
  • 1
    @John I'm slightly concerned also with your repeated mentions of a GUI. An HTTP Server *shouldn't* have a GUI. It should presumably be some sort of service, without a GUI. Of course I have no idea what you're actually trying to accomplish, so you may have some reason. Either way though, a non-responsive UI, combined with the fact that `TIdHTTPServer` already runs in the context of a thread, tells me you're doing something majorly wrong in the implementation. – Jerry Dodge Feb 23 '18 at 12:19
  • 1
    @Jerry, you don't like [flashing lights](https://www.youtube.com/watch?v=12LLJFSBnS4)? :) But anyway, if you were having a service and wanted to interact with the clients, you'd have to implement synchronization. – Victoria Feb 23 '18 at 12:35
  • @JerryDodge I have a webserver with a GUI, FWIW. It's a very special app mind you. It's a help browser. I embed a webhelp project into the app as a resource. The app is basically an embedded web browser. The embedded Indy webserver serves up content from the webhelp resource. Who knows what the asker is doing but it's not beyond the realms of possibility that a process might have a webserver and a GUI. – David Heffernan Feb 23 '18 at 12:37
  • @David Indeed... "*Of course I have no idea what you're actually trying to accomplish, so you may have some reason.*" I've done such a thing too, with a browser. But like you said, "very special app". The main point though is the non-responsive GUI. – Jerry Dodge Feb 23 '18 at 12:39