Mark Williams
Members-
Content Count
282 -
Joined
-
Last visited
Everything posted by Mark Williams
-
ISAPI DLL concurrent requests
Mark Williams replied to Mark Williams's topic in Network, Cloud and Web
WebGarden? Is this when you increase the Maximum Worker Processes of the Application Pool above 1? If so, it works when I do this, but I appreciate it is not the solution and I have reduced it again to 1. Nothing in WebModule's OnCreate and onDestroy. BTW what event should I use to free objects etc? Nothing in the Event Viewer. I am writing everything to a log file. See my last but one post. Also, can you advise me how I can monitor the ActiveConnections property from the WebModule? I can't figure out how to access the Application object. BTW thanks. I'll get some test projects uploaded asap. -
ISAPI DLL concurrent requests
Mark Williams replied to Mark Williams's topic in Network, Cloud and Web
Web Web.config: <?xml version="1.0" encoding="UTF-8"?> <configuration> <system.net> <mailSettings> <smtp from=""> <network host="" /> </smtp> </mailSettings> </system.net> </configuration> I'll have to work on a MCVE. But do you have any suggestionsat this point why multi-threading may not to be working? -
ISAPI DLL concurrent requests
Mark Williams replied to Mark Williams's topic in Network, Cloud and Web
I think maybe I didn't explain myself very well. Apologies. Plus I have managed to improve things a little since my first post. I noticed that my DLL was including Madshi's exception units. I have removed these and there is now an improvement. Whereas the DLL appeared to be hanging on concurrent calls resulting in a timeout error, my client app now gets a ENetHTTPClientException "Server returned an invalid or unrecognised response". But whereas the DLL was freezing it now continues to run albeit rejecting any concurrent requests. I don't know what code to post as I am not getting any exceptions for any of my event handlers (I do have the event wrapped in try except blocks). I add a log entry in the BeforeDispatch event to advise what method etc has been called and one in the AfterDispatch to advise when it is done. I log the http response codes issued by the handlers when they are done. I have set up a test app to fire off rapid requests via threads to download 14 files at slightly staggered intervals (10ms) so that they overlap. Accordingly, there are probably 14 concurrent requests being made at the same time. Only 1 returns successfully all the others fire a ENetHTTPException. The first request executes correctly. I log the BeforeDispatch and AfterDispatch events and these fire ok. I also log the Response returned by the dlls' download method and this logs correctly for the first call, which means it has completed okay. For concurrent calls, the BeforeDispatch event is not called. Also, within each method I log the fact it has been called as the first line of the method's code. For concurrent calls, the DLL is not even entering the handler for the method being called. It does not trigger any exception even though wrapped in a try except block. I think the problem is a threading problem within the DLL, but I don't understand why. As mentioned above, if within the ISS ApplicationPool for the DLL I increase the number of Maximum Working Processes above 1 then all is okay (presumably as long as I don't make concurrent requests that exceed the max working processes) save for the fact that each (concurrent?) request seems to run a new DLL instance rather than making use of DLL threading. Whilst this sort of resolves the problem, I am certain it is not the way to do this from all I have read on the web. To get threading working I can't work out whether there is something I need to configure on my website (it is configured for limitless connections), the ApplicationPool (can't see anything) or the app (and I used the wizard to create it so I would have thought not.. Below is the code from the DLL dpr file: library MWCWebServer; uses Winapi.ActiveX, System.Win.ComObj, System.SysUtils, Web.WebBroker, Web.Win.ISAPIApp, Web.Win.ISAPIThreadPool, WebModule in 'WebModule.pas' {WebModule1: TWebModule}; {$R *.res} exports GetExtensionVersion, HttpExtensionProc, TerminateExtension; begin try CoInitFlags := COINIT_MULTITHREADED; Application.Initialize; Application.WebModuleClass := WebModuleClass; {Application.MaxConnections:=200; NumberOfThreads:=Application.MaxConnections; Application.CacheConnections:=true;} Application.Run; end. I have tried setting MaximumConnections, CacheConnections. NumberOfThreads and none of these seem to do anything. But I can't imagine for a moment that the default no of threads for a webmodule is 1. So I guess it has to be something else. I have tried to monitor how many connections there are. But within the webModule I cannot figure out how to access the Application property! -
ENetHTTPRequestException exception Error adding header: (87) The parameter is incorrect.
Mark Williams posted a topic in Network, Cloud and Web
This is in connection with the AddHeader function of the IHTTPRequest. I'm trying to add a multiline text which also contains numerous characters such as = signs etc. I am getting the above error as a result. Is it even possible to do this? Should I be formatting the text in some way before adding it? UrlEncode? -
ENetHTTPRequestException exception Error adding header: (87) The parameter is incorrect.
Mark Williams replied to Mark Williams's topic in Network, Cloud and Web
Thanks. I do write both server and client. I have it working with multiformdata at moment and am going to leave it at that for now as this is a fairly minor part of a hefty development and I have managed to get myself bogged down in it. I will revisit it when I have a bit more time and do some research online. But thanks for all your help. -
ENetHTTPRequestException exception Error adding header: (87) The parameter is incorrect.
Mark Williams replied to Mark Williams's topic in Network, Cloud and Web
I tried Base64. This may have worked, but I think I'm running into a limitation as to permissible size of header. I absolutely agree that it is food for the payload, but I have tried and failed to submit/receive content using THTTPClient and TWebRequest components. My code for submitting the component is below, but when I try and access the TWebRequest's content it remains stubbornly empty. FHttpClient:=THttpClient.Create; try With FHttpClient do begin data:=TStringStream.Create; try data.WriteString(content); ContentType:='text/html'; Accept:='text/plain, */*'; AcceptCharSet:='utf-8'; LResponse:=FHttpClient.Post(Script, data); finally data.Free; end; end; I have now resorted to submitting it as multipartdata, which works, but seems overkill just to submit a string. -
ENetHTTPRequestException exception Error adding header: (87) The parameter is incorrect.
Mark Williams replied to Mark Williams's topic in Network, Cloud and Web
Hi Thanks, As far as I can see (and with my limited understanding of the protocols) it is compliant with the requirements for headers. Each line break is coded +Chr(32)+sLineBreak; There are no line breaks inserted other than in this manner, but I still get the error. Does anyone know of any function for encoding text in away that will satisfy the protocol? -
Trying to analyse the structure of a table using TFDMetaDataQuery with MetaDataKind set to mkTableFields. This returns just about everything I need apart from (as far I can see) a field's default value. I can see it returns TFDDataAttributes and that this includes an attribute caDefault which advises if a field has a default value, but I can see now way of ascertaining what the default value is. The metadata structure can be found at: http://docwiki.embarcadero.com/RADStudio/Rio/en/Metadata_Structure_(FireDAC)
-
FireDAC TFDMetaDataQuery default field value
Mark Williams replied to Mark Williams's topic in Databases
Thanks Lars. There is a query for PostgreSQL which will retrieve this info, but I was hoping to do it all with the MetaDataQuery. -
Floating point problems with external dlls
Mark Williams posted a topic in RTL and Delphi Object Pascal
I'm trying to use the TesseractOCR4 wrapper from GitHub. I have cloned the project and downloaded it. I get all the example projects to work as expected. However, I run into floating point operation errors with the dlls when I try and use it in my own application. I have all the necessary units included in my uses. I have copied all the necessary dlls to my application folder and also the test data. My app runs and loads the library fine and I can call the recognize function to extract the text. However, it extracts as a single word (ie with no gaps between words). I assume this is the default setting (although I can't imagine why). There is a PageSegMode property which can be used to change the way Tesseract recognizes the text. I can change this fine within the example apps, but whenever I try and set it in my own app to one of the pre-defined constants it causes a floating point violation within one of the dlls. I assume there must be some project option which is set/unset in my app which is causing this issue. Can anyone please point me in the right direction? -
Floating point problems with external dlls
Mark Williams replied to Mark Williams's topic in RTL and Delphi Object Pascal
No you are right. I have created a new project and copied the main form from the example project to my new project and then pointed my project at the copied form. It works fine. However, if I create a new project and replicate the form from the example folder, it keeps spitting out the floating point error. I have stripped back the example form so it consists of nothing more that a button and a TOpenDialog. I have pared back its code to about 20 lines and it still works okay. But when I try to recreate (rather than copy) the example form in a new project it bums out again. Even if I copy and paste the entire .pas unit for the example form into my new .pas and even if I right click and view as text and then paste from the example to the new form. So it seems to be something about the way the form is configured, but as to what that is I have no idea. -
Floating point problems with external dlls
Mark Williams replied to Mark Williams's topic in RTL and Delphi Object Pascal
That works in the sense that it masks the exception, but the operation basically stops early. The example applications do not use masking of this error and yet they work for me. I assume it has to be a different configuration of the project option, but I could not find any differences that appeared significant in this context although I update my project optiosn to align just in case and no joy. -
I thought I'd give the new inline variables a try in 10.3.1. When I enter eg "Var b:=true" it is underlined in squiggly red to indicate a code error (as are chunks of the subsequent code) but it compiles fine. I would like to use this new feature, but this is going to get me confused as to where actual errors do actually lie. Is this a bug or do I need to configure something in the IDE to stop this happening?
-
@Sherlock Error Insight (didn't know it was called that) seems to be working fine for me since at least 10.2. It is really useful. Compiling and re-compiling to detect errors is just so painful.
-
Thanks.
-
Do I really need to make that choice? As the inline vars compile ok they shouldn't be underlined as code errors. So I was wondering if there is an option I needed to configure in the IDE to prevent this issue or whether it is a bug in the new IDE. If it is not a configuration option then I assume it must be a bug. So I would rather not make the choice. I would rather get an answer and if it is a bug I will report it and hope it gets fixed.
-
I quite like the underlining of errors. Really handy to see at a glance where your errors are without having to recompile for each one.
-
Occasionally, when I am debugging a particular app, if there is a bug in a section of code, the debugger opens one of my units (always the same one and which wasn't previously open or changed) and reports a bug in a specific line in that unit. The report is wrong there is no bug. If I comment out the supposedly offending line in this unit and recompile I am taken to the correct bug. After I correct that, I can then go back to the incorrectly identified line uncomment and recompile successfully. Does anyone know why I am seeing this behaviour? I am using 10.3.1, but the issue was present at least as far back as 10.2
-
Random incorrect bug identification
Mark Williams replied to Mark Williams's topic in Delphi IDE and APIs
Yes. Sorry. Of course I meant exception. Thanks for the info. Will try that out and see if it is the problem. -
Do you design each form for separate case, or use common forms for similar design?
Mark Williams replied to Mike Torrettinni's topic in VCL
I have just discovered a component on the Windows 10 tab called TCardPanel. Seems very similar to a page control, but without the tabs. Maybe of some use. -
Best/Simplest way to dynamically populate TVirtualStringTree from database
Mark Williams posted a topic in Algorithms, Data Structures and Class Design
I am using TvirtualTree for data display where there can be large numbers of records in a database table (upwards of 30,000). Given the virtual paradigm, it obviously makes sense to query for the data only as needed. But I am struggling to find the best way of dealing with this. It is not ideal to query for the data simply on the firing of the onScroll event. It would just mean that scrolling would become gruesomely slow. I did try to implement something based on the following design: Use the OnScroll event to fire a timer with an appropriate interval to indicate the user has stopped scrolling for a spell (eg 500ms). Record the topNode at start of timer. After timer interval check if TopNode has changed. If TopNode hasn't changed, query whether data already obtained for the nodes within the tree's visible area. If data needed, obtain it via a thread so as not to inhibit further scrolling of the tree. Populate the tree with the new data assuming user hasn't scrolled on since the thread executed. I managed to get this working after a fashion. but it didn't strike me an elegant solution (nor in fact was it terribly reliable probably due to y design). I am about to revisit this again. It occurs to me that as the virtual paradigm is key to VirtualTree this problem must have been considered and resolved as part of the tree's design so as to greatly simplify the process. If that is so, I can't find out what the solution is meant to be and would be grateful for any pointers. If there is no easy solution as part of the tree design I would be grateful for a steer as to other ways of reliably and (hopefully) simply resolving this issue. -
Best/Simplest way to dynamically populate TVirtualStringTree from database
Mark Williams replied to Mark Williams's topic in Algorithms, Data Structures and Class Design
I already handle it in a separate thread so that's all set to go. I use a separate thread also to check for any new records/changes etc. I'll test the encryption side. I have the feeling that the locally stored database will be 10s of MBs for a database with around 10,000 records. My experience of strong encryption for files of that magnitude is that it is slow. There's also the issue of where to store the encryption key. Hard-coded within the app is not a good idea. I could store it on the server and retrieve it on start up, but then the key is something which should probably be regularly changed for security reasons, which would then render the local file inaccessible. I suppose you just load it all over again from the server. -
Best/Simplest way to dynamically populate TVirtualStringTree from database
Mark Williams replied to Mark Williams's topic in Algorithms, Data Structures and Class Design
OK. Food for thought. TFDQuery has saveToStream abilities. So could be saved to a local file. Encrypting and decrypting such a hefty file would probably take a while, but probably better than the hit on the server. Certainly another option. -
I am using Array DML to post data to a postgres table. One of the fields is of type bytea. I have tried setting the datatype for the relevant query parameter toftBlob. This fails with the error: I have tried setting the datatype for the query parameter to the same TFieldType as the field in the FireDAC dataset. I get the same error, so it would seem the field is a blob field. Code below: Query2,Params[3].DataType:=ftBlob; Query2Params[3].AsStream:=CreateBlobStream(Fields[ages], bmRead);
-
Thanks for the info. I gave up on byteA in the end. The data is an array of numbers. I now save it to csv and in a text field and then restore it to an array when needed. There does not seem to be any appreciable loss of speed. Would have certainly looked at ftStream otherwise.