2

I am using the OmniThreadLibrary in a Delphi 2007 app that utilises the global thread pool to preform some file operations (I need to try and make sure they are done in a specific order).

I have the contents of a newly created Ini file that is stored in a TStringList.

I then pass the TStringList to an instance of TOmniTask.

class procedure saveIniFile(const iniFile: TStringList);
    var
        task  : IOmniTaskControl;
    begin
        task := CreateTask(saveIniFileTask, 'saveIniFile')
                   .SetParameter('iniFile', iniFile)
                   .Unobserved
                   .Schedule;
    end;

I cannot figure out how to retrieve the TStringList in the TOmniTask instance

class procedure saveIniFileTask(const task: IOmniTask);
    var
        iniFile: TStringList;
    begin
        iniFile := task.Param['iniFile'];
    end;

The above would return an error:

Incompatible types: 'TStringList' and 'TOmniValue'

I have tried typecasting:

iniFile:= TStringList(task.Param['iniFile'].AsObject);

But get a compiler error:

F2084 Internal Error: C4310

I am using OmniThreadLibrary version 3.0 - I cant get 3.03b to compile in D2007

If @gabr is about: Great piece of work OmniThreadLibray, thank you.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Gavin
  • 2,123
  • 1
  • 15
  • 19
  • 1
    The `Internal Error` is a bug in the compiler and shouldn't have happened no matter what you did. The compiler obviously got confused. What happens if you do `myObject := task.Param['iniFile'].AsObject;` and then `iniFile:= myObject as TStringList;`? – 500 - Internal Server Error Sep 19 '14 at 13:11
  • @David Heffernan - thanks very much, I created a temporary TObject and read the TOmniValue.AsObject and then typecast the Tobject to TStringList. – Gavin Sep 19 '14 at 13:26
  • Your expression requires the compiler to create a temporary local TOmniValue, and manage its lifetime (it has managed types in the record). That's probably the factor that is giving the compiler indigestion. – David Heffernan Sep 19 '14 at 13:31
  • Indeed, you are using a correct approach but the compiler has problems ... David's solution is correct. Once you upgrade to a more modern Delphi, you can also do `task.Param['iniFile'].AsObject`. – gabr Sep 20 '14 at 08:45
  • About the compilation errors - I'll check what's going on. I'm not using D2007 anymore and such problems can creep in. – gabr Sep 20 '14 at 08:46
  • @gabr Thanks for the reply. I've managed to get hold of D2010 and everything works as documented. Davids' solution worked well in D7. Once again, great bit of work. Thanks for making it available. – Gavin Oct 10 '14 at 17:59

1 Answers1

3

F2084 Internal Error: C4310

This is an internal compiler error. That is a compiler bug. Your code is fine, but the compiler gags for some reason.

Look for a workaround. I expect the compiler is freaked out by your combining an array property read and a plain property read and a cast in a single expression. Nothing wrong with your code, but the compiler can sometimes be easily confused.

The obvious thing to try is to feed the compiler simpler expressions. For instance, try storing to a local variable, and then casting:

var
  obj: TObject;
....
obj := task.Param['iniFile'].AsObject;
iniFile := TStringList(obj);

Or if it doesn't like that, go one step further:

var
  ov: TOmniValue;
  obj: TObject;
....
ov := task.Param['iniFile'];
obj := ov.AsObject;
iniFile := TStringList(obj);

Or maybe you can get away with:

var
  ov: TOmniValue;
....
ov := task.Param['iniFile'];
iniFile := TStringList(ov.AsObject);

You should be able to get something in this vein to work.

FWIW, I would advise a checked cast here:

iniFile := ov.AsObject as TStringList;
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490