-
Content Count
2854 -
Joined
-
Last visited
-
Days Won
156
Posts posted by Anders Melander
-
-
Assuming you meant AnsiString and not AnsiChar (it doesn't make sense to compare 13 bytes to 1 ansichar):
function Compare(const Bytes: TByteArray; const Str: AnsiString): boolean; begin Result := (Length(Str) = SizeOf(Bytes)) and (CompareMem(@Str[1], @Bytes[0], SizeOf(Bytes)); end;
-
I think you must have a bug somewhere else that is causing this. I can't spot a problem in the code you've posted.
The following works for me with D10.3.1:
function Test1: OleVariant; begin Result := VarArrayCreate([0, 1], varOleStr); Result[0] := 'Hello'; Result[1] := 'World'; end; function Test2: OleVariant; var V: OleVariant; begin V := VarArrayCreate([0, 1], varOleStr); V[0] := 'A kitten dies...'; V[1] := '...every time you use variant arrays'; Result := V; end; procedure DoTest; var V: OleVariant; begin V := Test1; V := Test2; end;
Try reproducing the problem in a new empty application.
-
Have you tried VarArrayCreate(..., varOleStr)?
1 hour ago, Gregory Koehn said:This does not work either gives error on result := V
I can't see why you would get an error assigning one OleVariant to another but it would help if you specified what error you're getting.
-
21 hours ago, dkounal said:Can different threads use TFDMemTables object instances (created with data from clonecursor) from an initial TFDMemTable? Is this threadsafe?
Yes. Moving the cursor in a clone does not affect the other clones.
5 hours ago, Lachlan Gemmell said:Back in 2014 the lead architect of FireDAC confirmed it is not threadsafe.
As I read that post read access to a cloned dataset is thread safe.
-
1
-
-
1 minute ago, Remy Lebeau said:But not the message queue, no.
Yes, it was poorly expressed on my part. If they went through the message queue then the application wouldn't appear hung.
-
18 minutes ago, clubreseau said:why this freeze the APP and take 1 minut to load 10K of items ?
Generally speaking, the API of most Windows common controls goes through the windows message queue. So my guess is that for each item in the listbox there's a lot of messages going back and forth while the listbox is populated and that's an enormous overhead.
If you break the application in the debugger while the list is loading you can see what it's doing.
-
48 minutes ago, Mike Torrettinni said:Thank you, but that was very confusing to read, the whole page.
Okay. I'll try with a simpler example (apologies to @Kas Ob. if he/she/they already covered it, but it's friday and TLDR).
Byte code is just the instruction set for a specialized virtual CPU so in this case it's a virtual CPU that only knows how to search stuff.
A byte code compiler is a compiler that transforms "something" (in this case search parameters) into the virtual CPU assembler.
The implementation of the virtual CPU is called an interpreter if it executes the byte code instruction from scratch each time you execute the "byte code program". If it instead compiles the byte code into actual processor opcodes the first time and then execute those the first and subsequent times, then it's called just-in-time compiler.
One of the first pascal implementation was UCSD Pascal which ran on the UCSD p-System - a byte code virtual machine.
P.S. You really should try to read about and understand these old concepts. While they might not seem relevant to you now, understanding and knowing about them can only improve your skills.
-
1
-
1
-
-
-
So you are doing it with Outlook which again prompts me to ask why you're not also handling the eml files the same way (after importing them into Outlook) instead of handling them in two different ways?
Personally I would probably:
- Load the msg file into an IStorage with StgOpenStorage
- Get an IMessage from the IStorage with OpenIMsgOnIStg
- Extract the IMessage properties with HrGetOneProp or IMessage.OpenProperty
-
1 minute ago, Mark Williams said:I am processing the email files for upload to a server. I don't need to add them to Outlook to do this. If I can open and handle them via TIDMessage it will save a significant amount of time.
Yes I understood that. I was talking about your statement : "drop the msg files into Outlook and handle them there somehow".
-
37 minutes ago, Mark Williams said:... and Outlook for any emails TIDMessage can't handle by adding the latter to a temp folder in Outlook, processing and then removing the temp folder (subject to me working out exactly how I do that!).
If I'm understanding what you're saying you are going drop the msg files into Outlook and handle them there somehow. If that's an option then why not also handle the eml files this way?
-
16 minutes ago, Mark Williams said:Off hand do you happen to know if most other email types are also structured storage files?
I would guess that no other types use it. It's not a very friendly format.
18 minutes ago, Mark Williams said:Do you (or anyone) happen to know know if the IMessage interface will work with other email types or just Outlook?
I can't speak authoritatively on the subject but if IMessage is a MAPI interface then in theory it should work with all MAPI providers. Unfortunately I don't think there's many applications left that support MAPI.
23 minutes ago, Mark Williams said:I would really appreciate any feedback on whether TIDMessage can handle MSG files
I doubt it but it should be easy to determine since you have the source...
-
1
-
-
Outlook msg files are COM Structured Storage files in the CFB3 (Compound File Binary) format.
Here's file file format specification: http://msdn.microsoft.com/en-us/library/cc463912.aspx
You can use the IStorage interface to load the file (via IStream) but you will need to locate and extract the desired properties manually. You can find tons of code on the net that shows how to do that and I think the above specs contains the names of the properties. I also think the last version of the Drag and Drop Component Suite I released even contained some code that did it.
AFAIR there's also an OpenIMsgOnIStg API function that can do some of the work for you but I think it might require that Outlook is installed.
-
1
-
-
Just now, A.M. Hoornweg said:I'd like to take a closer look at it at the very least !
Okay, here you go. Source and simple demo attached.
Usage:
Producer
var FRingBuffer := TSharedMemoryRingBuffer.Create('FooBar', 1024*1024); // 1Mb ... // String FRingBuffer.Enqueue('Hello world'); // Raw bytes var Buffer: TBytes; ... FRingBuffer.Enqueue(Buffer);
Consumer
var FRingBuffer := TSharedMemoryRingBuffer.Create('FooBar', 1024*1024); // 1Mb ... // Strings while (True) do begin // Just remove the WaitFor to use polling instead if (FRingBuffer.WaitFor(100) = wrSignaled) then begin var s. string; if (FRingBuffer.Dequeue(s)) then ...do something with string... end; ... end; // Raw bytes while (True) do begin // Just remove the WaitFor to use polling instead if (FRingBuffer.WaitFor(100) = wrSignaled) then begin var Buffer: TBytes; if (FRingBuffer.Dequeue(Buffer)) then ...do something with buffer... end; ... end;
-
2
-
-
@A.M. Hoornweg Thanks for the detailed explanation. I understand your challenge much better now.
I think it's essential that you realize that the overhead of the lock itself is not going to be a factor at all and instead focus on minimizing the time the lock is held - i.e. the time to transfer data to and from the shared memory buffer. My recommendation would be to start with a simple solution and if that turns out not to be fast enough then you can try to come up with something better.
I don't know anything about the actual amount of data you're processing but I think I would strive to process it in many small chunks instead of few large chunks. On the producer side I would write data packets to a (fast) lock free queue and have a separate thread read from that queue and write them to the (slower) shared memory queue. If it's essential that the producer isn't blocked then you will have to accept that data can be dropped if the consumer isn't able to keep up, but I guess you already know that.
Again, if you want it I have a ready to use implementation of a shared memory circular buffer that has been used in production for many, many years.
-
1 hour ago, A.M. Hoornweg said:The producer writes into the ring buffer @ 10Hz, the consumer polls the ring buffer every few seconds and pulls whatever was put in there.
Are you kidding me?
What you are asking for is apparently a wheelbarrow while the rest of us are suggesting different ways to build a drag racer
I don't get why you don't just use a TMutex to protect the ring buffer structure and a TSemaphore to signal availability. I mean it's like around 10 lines of extra code compared to the 2-300 lines of code you will need to implement the ring buffer in shared memory.
1 hour ago, A.M. Hoornweg said:A synchronization object is only needed for atomicity of the pointers and counters.
You're aware that you can't store pointers in shared memory, right?
-
4 hours ago, FPiette said:InterlockedCompareExchange can be used to implement a spinlock. When using shared memory, this will work interprocess.
So how will you use a spinlock to signal the consumer thread that data is available without doing busy wait?
-
5 minutes ago, Mahdi Safsafi said:WaitOnAddress apparently works only with threads in the same process
And it's extremely subject to race conditions. https://devblogs.microsoft.com/oldnewthing/20160826-00/?p=94185
-
1
-
-
Why not just use the traditional synchronizations mechanism provided by the OS and keep things simple? It seems pointless focusing on micro optimizing the concurrency control of a buffer backed by virtual memory and accessed synchronously. The sync mechanism is not going to be the bottleneck.
I have the code for a shared memory ring buffer somewhere if the OP is interested. I used it a few decades ago to pipe CodeSite log messages between a producer and a consumer service. The consumer wrote the log to disk.
-
1
-
-
53 minutes ago, dkounal said:Comments, suggestions, errors in the code welcome.
Call me old fashioned but the way you've formatted your code makes it close to unreadable to me.
-
1
-
-
Instead of waiting on the back and forth I'll assume that what we have here is a classic case of the XY problem.
To determine what properties a WMI object exposes you can use a tool like WMI Explorer (there are many other tools like that, this is just the first one I found).
-
1 hour ago, A.M. Hoornweg said:does the "Interlockedxxxx" API work reliably across process boundaries ?
Yes.
-
On 10/28/2020 at 4:45 PM, Phil Brinkle said:Your code works fine and it returns 36 functions for me
Those are just the WMI methods and they are all documented.
https://docs.microsoft.com/en-us/windows/win32/api/wbemcli/nn-wbemcli-iwbemclassobject
If you want to talk to a COM server why are you then going through WMI? Are you sure it isn't a WMI Provider you are talking about?
52 minutes ago, Phil Brinkle said:I am working with an undocumented COM server.
If you install the Windows SDK (just the tools parts) there's a utility in it called OleView that you can use to examine type libraries and COM servers.
The type library of your server is probably embedded in the EXE file.
Edit: If it's a WMI provider then it's probably a DLL and it's probably early bound and without a type library. It depends on what kind of provider it is.
-
1
-
-
On 10/28/2020 at 10:02 PM, Dany Marmur said:Seriously, don't worry, i avoid OLE like i do Covid.
Maybe if you learned the difference between OLE and COM you wouldn't be so scared... Hardly anyone uses OLE anymore.
Compare byte array to ansichar
in Delphi IDE and APIs
Posted
As I wrote you cannot compare a byte (ansichar) to 13 bytes (byte array) for equality. Since the size is different they will always be different, so what you're asking isn't making sense.
Are you trying to determine if the byte array contains the ansichar?