Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: Обёртка для глобальных объектов, используемых потоками (TThreads)

Добрый день!

Есть большая программа с несколькими потоками (TThreads) и парой десятков глобальных объектов, к которым эти потоки обращаются произвольным образом. Каждый из глобальных объектов может обращаться к другому глобальному объекту. Каждый из глобальных объектов имеет свою критическую секцию. Глобальные объекты наследуют разные классы.

Принято решение оставить только одну критическую секцию на всю программу. При этом прямой доступ к указанным глобальным объектам закрыть, обернув их все в один класс. Этот класс будет отдавать ссылки на глобальные объекты только после его блокировки (как TThreadList).

Таким образом (1) мы будем уверены, что обращаемся только к заблокированным объектам и (2) не надо следить за последовательностью блокировок разных критических секций. Обращение от одного глобального объекта к другому будет внутри одной блокировки.

Упрощенный каркас описан ниже. Мне не нравится не очень изящный механизм реализации общения объектов между собой. Существуют ли иные решения? Критически важным параметром является скорость доступа к объектам и между объектами.

Глобальный локер-обёртка (TLocker + TContainer):
+
unit TestLockerUnit;

interface
uses
  SyncObjs, Obj1Unit, Obj2Unit;

type
  TLocker = class;

  TContainer = class
  private
    FLocker : TLocker;
    FGlobalObject1 : TLockedObject1;
    FGlobalObject2 : TLockedObject2;
  public
    constructor Create;
    destructor Destroy; override;
    property GlobalObject1: TLockedObject1 read FGlobalObject1;
    property GlobalObject2: TLockedObject2 read FGlobalObject2;
  end;

  TLocker = class
  private
    FContainer : TContainer;
    FCS : TCriticalSection;
  public
    constructor Create;
    destructor Destroy; override;
    function Lock : TContainer;
    procedure Unlock;
  end;

var
  Locker : TLocker;  // Это единственный глобальный объект

implementation

{ TLocker }

constructor TLocker.Create;
begin
  inherited;
  FContainer := TContainer.Create;
  FCS := TCriticalSection.Create;
end;

destructor TLocker.Destroy;
begin
  FContainer.Free;
  FCS.Free;
  inherited;
end;

function TLocker.Lock: TContainer;
begin
  FCS.Enter;
  Result := FContainer;
end;

procedure TLocker.Unlock;
begin
  FCS.Leave;
end;

{ TContainer }

constructor TContainer.Create;
begin
  inherited Create;
  FGlobalObject1 := TLockedObject1.Create(Self);
  FGlobalObject2 := TLockedObject2.Create(Self);
end;

destructor TContainer.Destroy;
begin
  FGlobalObject1.Free;
  FGlobalObject2.Free;
  inherited;
end;

end.

Один глобальный объект (TLockedObject1):
+
unit Obj1Unit;

interface

type
  TLockedObject1 = class
  private
    FContainer : TObject;
  public
    constructor Create(AContainer : TObject);
    procedure Work1;
    procedure Work1a;
  end;

implementation
uses
  TestLockerUnit, Obj2Unit;

constructor TLockedObject1.Create(AContainer: TObject);
begin
  inherited Create;
  FContainer := AContainer;
end;

// 1-й вариант использования глобального объекта 2:
procedure TLockedObject1.Work1;
begin
  with (FContainer as TContainer) do
    GlobalObject2.Work2;
end;

// 2-й вариант использования глобального объекта 2:
function GetGlobalObject2(AContainer : TObject) : TLockedObject2; inline;
begin
  Result := (AContainer as TContainer).GlobalObject2;
end;

procedure TLockedObject1.Work1a;
begin
  GetGlobalObject2(FContainer).Work2;
end;

end.

Другой глобальный объект (TLockedObject2):
+
unit Obj2Unit;

interface
type
  TLockedObject2 = class
  private
    FContainer : TObject;
  public
    constructor Create(AContainer : TObject);
    procedure Work2;
  end;

implementation
uses
  TestLockerUnit, Obj1Unit;

constructor TLockedObject2.Create(AContainer: TObject);
begin
  inherited Create;
  FContainer := AContainer;
end;

procedure TLockedObject2.Work2;
begin
{ Разумеется, не вызываем Work1, т.к. из него вызывается Work2. Это просто пример обращения к соседу
  with (FContainer as TContainer) do
    GlobalObject1.Work1;
}
end;

end.

Сорри за длинный текст.
Ответ: schi,

Вовсе не обязательно!
Alex724
Глобальные объекты наследуют разные классы
... и выполняют совершенно разные функции. А еще они большие. Зачем из них делать один объект? Чтобы вскрыться? :)
Вопрос: DBX: Access violation при обращении к свойству InTransaction объекта SQLConnection

Добрый день. В программе возникает ошибка "Access Violation" при попытке обратиться к свойству InTransaction объекта TSQLConnection. Пример кода:

begin
  if assigned(SQLConnectrion) then
    if SQLConnectrion.InTransaction then SQLConnection.StartTransaction(TransDesc);
  try
    // здесь код работы с БД (вызовы хранимых процедур)
  except
    on e: exception do
        begin
          if Assigned(SQLConnectrion) then
            if SQLConnectrion.InTransaction then SQLConnectrion.Rollback(TransDesc);
          raise;
        end;
  end;
end;


Обращение к свойству SQLConnection.InTransaction до блока try срабатывает корректно, а обращение в блоке except вызывает Access Violation. В чем может быть причина?
Ответ:
_Vasilisk_
Interloper
Ссылка на компонент передается в процедуру как параметр.
Interloper
пропущено...

Компонент.
Одно из этих утверждений ложно

Это компонент на форме, который передается в процедуру по ссылке. А мог бы быть динамически создаваемый в ран-тайме объект.
Вопрос: Проблема с работой в потоке при обращении к элементу другой программы (АвтоКАДа)

Здравствуйте!
Пытаюсь сделать в Дельфи (D7) программу, которая в потоке будет менять цвет объекта из АвтоКАДа (мигать).
Проблема возникла вот какая: почему-то функция смены цвета работает в Create потока, а в Execute любое обращение к АвтоКАДу вызывает проблемы (всё зависает разными способами).
Перепробовал несколько разных вариантов, остановился на этой реализации:
Код:

type
  TACTF = record
    excolot: Integer;  // цвет объекта
    Ent: IAcadEntity;  // объекта в АвтоКАДе (интерфейс)
    Handl: string;  // Хендл (идентификатор) объекта в АвтоКАДе
  end;
  TOneMoreThread=class(TThread)
  private
    AcadApp: IAcadApplication;  // Интерфейс самого АвтоКАДа
  protected
    procedure execute; override;
  public
    ArrObj: array of TACTF;
    constructor Create(HandStr:TStringList);
    destructor Destroy; override;
  end;
  ...
  TForm1
    ...  
  private
    OneMoreThread:TOneMoreThread;
    HandStrs: TStringList;   // Список хендлов объектов, забираемых из StringGrid

    ...
  
 Procedure SetEntColor(HandNom: integer; Col: integer);
var
  Ent: IAcadEntity;
begin
  Ent:=(Form1.AcadApp.ActiveDocument.HandleToObject(Form1.HandStrs[HandNom]) as IAcadEntity);
  Ent.color:=Col;
  Ent.Update;
end;

procedure TOneMoreThread.execute;
var
  i, Nom:Integer;
begin
  inherited;
  Nom:=0;
//  While not terminated do
//  begin
    inc(Nom);
    Form1.Caption:=IntToStr(Nom)+' st'+ArrObj[0].Handl;
    SetEntColor(0,acRed);  //  даже такая реализация не работает: глюков не происходил, но до Form1.Caption:=IntToStr(Nom)+' ch' так и не доходит
    For i:=0 to Length(ArrObj)-1 do
    begin
//      ArrObj[i].Ent.color:=acRed;  
//      ArrObj[i].Ent.Highlight(True);
    end;
    Form1.Caption:=IntToStr(Nom)+' ch';
    Sleep(1000);
    Form1.Caption:=IntToStr(Nom)+' sch';
//    SetEntColor(ArrObj[0].Ent,ArrObj[i].excolot);
    For i:=0 to Length(ArrObj)-1 do
    begin
//      ArrObj[i].Ent.color:=ArrObj[i].excolot;
//      ArrObj[i].Ent.Highlight(False);
    end;
    Form1.Caption:=IntToStr(Nom)+' en'+ArrObj[1].Handl;
    Sleep(2000);
//  end;
end;

constructor TOneMoreThread.Create(HandStr:TStringList);
var
  i: integer;
begin
  inherited Create(True); (*Поток создаем в состоянии «Приостановлен»*)
  AcadApp:= GetAcadApplication(true);
  SetLength(ArrObj,HandStr.Count);
  If HandStr.Count>0 then
  begin
    for i:=0 to Length(ArrObj)-1 do
    begin
      ArrObj[i].Ent:=(AcadApp.ActiveDocument.HandleToObject(HandStr[i]) as IAcadEntity);
//      SetEntColor(ArrObj[i].Ent,acRed);   // <------------  В этом месте изменение цвета работает!
//      ArrObj[i].Ent.Update;

      ArrObj[i].excolot:=ArrObj[i].Ent.color;
      ArrObj[i].Handl:=ArrObj[i].Ent.Handle;
    end;
  end;
  FreeOnTerminate := True; (* Поток освободит ресурсы при окончании работы*)
  Self.Priority := tpNormal;
  resume;
end;

destructor TOneMoreThread.Destroy;
begin
  AcadApp:= nil;
  SetLength(ArrObj,0);
  inherited Destroy;
end;


procedure TForm1.Button15Click(Sender: TObject);
var
  NCol,i:Integer;
begin
  NCol:=StringGrid1.Selection.Left;
  If NCol=1 then NCol:=2; If NCol=3 then NCol:=4; If NCol=5 then NCol:=6;
  HandStrs:=TStringList.Create;
  For i:=StringGrid1.Selection.Top to StringGrid1.Selection.Bottom do
    if StringGrid1.Cells[NCol,i]<>'' then
      HandStrs.Add(StringGrid1.Cells[NCol,i]);
  OneMoreThread:=TOneMoreThread.Create(HandStrs);
end;

procedure TForm1.Button16Click(Sender: TObject);
begin
  OneMoreThread.Terminate;
  HandStrs.Free;
end;

Ответ:
Цитата:
если synchronize использует основной поток, то чьими переменными он пользуется?
всеми которые доступны с т.з. компилятора. (переменная это понятия компилятора, не программы).

правило разрешения имен. Какая "переменная" c таким именем будет использована.
1. локальные имена (в т.ч. параметры процедур).
Код:

procedure One;
var
  x: integer;
begin

2.внутренние поля объекта(для процедур-методов)
Код:

TmyClass 
  x: string;
  ...
end;

procedure TMyclass.OneX;
begin

3. имена объявленные в ТОМ же unit
Код:

var
  x: TDateTime;

procedure Two; 
begin

4. имена объявленные в ДРУГИХ unit подключенных с использованием uses в порядке их перечисления.
в некоторых случаях при наличии одинаковых имен это приводит к проблемам.


все нарушения(коррекции) порядка использования лечатся использованием составных имен
1. добавлением имени модуля
Код:

unit5.x :=strtount( unit6.x );

2. добавлением имени объекта
Код:

var
  obj1: TmyClass;

procedure XX;
var
  x: integer;
begin
  x:=strtoint(obj1.x);

Вопрос: Сылки на объекты

Часто встречаю такую странную форму записи, когда на объекте, на который нет ссылки, вызываются методы.
Мне кажется, что всё-таки есть на объект А какой-то адрес, и это как-то связанно с this. Иначе непонятно как он ищется в хипе.
Ответ:
Сообщение от Welemir1
анонимный класс
Где? Тут все классы конкретные: A и B.

Сообщение от Valeera1
а здесь this как-то подвязано?
Да. В методах объекта (например в методе equals) она всё так же доступна.

Сообщение от Valeera1
И всё-таки как насчет адреса на этот объект, как его можно получить?
Никак.

Сообщение от Valeera1
на который нет ссылки
Сообщение от Valeera1
Иначе непонятно как он ищется в хипе.
Кем ищется?

Сообщение от Welemir1
Если тебе прямая ссылка то создавай обычный объект и переменную, анонимный классы потому и используют, чтобы не заморачиваться с объектами и ссылками.
Чего?

Добавлено через 38 секунд
Сообщение от Valeera1
киньте плз почитать об этой штуке что-то
О какой штуке? Создали объект, вызвали метод. Что тут непонятного?

Добавлено через 12 минут
Сообщение от Welemir1
анонимный классы потому и используют, чтобы не заморачиваться с объектами и ссылками.
Если создать объект анонимного inner-класса, то объект этого класса будет хранить ссылку на объект outer-класса, поэтому, например, если inner-класс реализует интерфейс Serializeable а outer-класс — нет, при попытке сериализовать объект внутреннего класса, выбросится исключение.

Другое дело объекты, создаваемые лямбда-выражениями в Java 8. Если в их коде нет явного обращение к outer-объекту, то ссылку на него они не хранят.

Добавлено через 19 минут
Например:

Java(TM) 2 Platform Standard Edition 5.0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.function.Consumer;
 
public class Outer {
    
    public static void main(String[] args) {
        test("Anonymous class", new Outer().getInner());
        test("Lambda expression", new Outer().getLambda());
    }
    
    private static void test(final String mark, final Serializable object) {
        try (final ObjectOutputStream out = new ObjectOutputStream(System.out)) {
            out.writeObject(object);
        } catch (final IOException e) {
            System.err.println("ERROR [" + mark + "] "
                    + e.getClass().getSimpleName() + e.getMessage()
            );
        }
    }
    
    public Serializable getInner() {
        return new Serializable() {
            private static final long serialVersionUID = 6570814919061667385L;
        };
    }
    
    public SerializableConsumer<Void> getLambda() {
        return (ignore) -> {
        };
    }
    
    private static interface SerializableConsumer<T> extends Consumer<T>, Serializable {}
}
Вопрос: Сброс изменений загруженного из бд сущностного объекта

Добрый день!

Помогите, пожалуйста, разобраться с проблемой. Есть, как я думаю, достаточно стандартная задача. Но не хотелось бы изобретать велосипед для ее решения или использовать какие-то неоптимальные, неправильные решения.
Суть в следующем. По средствам EF6 загружается коллекция сущностных объектов. Коллекция отображается на форму. На форме отображается список элементов и подробно текущий элемент со всеми свойствами и связями. Пользователь редактирует текущий элемент, потом приходит к выводу, что что-то сделал не так. Ему необходимо предоставить кнопку "сброс". При нажатии на нее текущий, редактируемый элемент сбрасывается в состояние на момент загрузки. Все изменения откатываются. Причем как изменения в простых свойствах объекта, так и свойствах коллекциях связанных объектов, свойствах навигации (если что-то добавилось - убрать, удалилось - восстановить, было изменено - откатить изменения).
Т. к. EF хранить OriginalValues, предполагал что есть какой-то стандартный метод для такого случая. Типо reset(), например в классе DBEntityEntry. Но такого нет. Единственное что есть, Reload(). Но повторная загрузка из БД не нужна. Да и необходимо сбросить вместе с самим объектом и его определенные загруженные связи. В общем не пойдет. Есть вариант для сброса обойти все свойства объекта, для измененных в CurrentValues записать OriginalValues, состояние объекта поменять на Unchanged. Потом пройтись по всем свойствам коллекциям, проверить состояние каждого элемента коллекции, в зависимости от состояния выполнить соответствующие изменения (для добавленных удалить из коллекции, удаленные восстановить и т. д.), для измененных записать в CurrentValues OriginalValues. Но это кажется слишком замороченным и похоже на изобретение велосипеда. Может кто-то подскажет оптимальное, разумное решение? Спасибо.
Ответ: Т. К. dbContext у меня обернуть в Repository, то наряду с методом SaveAll(), который просто вызывает SaveChanges() на контексте, реализовал метод RejectAll(). Проблема была только с восстановлением удаленных сущностей, которые перед удалением были модифицированы и изменения не были сохранены. Для таких есть два варианта решения. В коде (1) и (2). (1) - использует обращение к базе, мне этого не нужно, поэтому я использую (2).

public class BaseRepository<TEntity, TKey, TContext> : IRepository<TEntity, TKey>
     where TEntity : class, IEntity<TKey>
     where TContext : DbContext, new()
     {
          public virtual void RejectAll()
        {
            foreach (var entry in this.Context.ChangeTracker.Entries().Where(x => x.State != EntityState.Unchanged))
            {
                switch (entry.State)
                {
                    case EntityState.Modified:
                        //При установке состояния объекта в Unchanged из Modified 
                        //в CurrentValues записываются OriginalValues
                        entry.State = EntityState.Unchanged;
                        break;

                    case EntityState.Added:
                        entry.State = EntityState.Detached;
                        break;

                    case EntityState.Deleted:
                        //(1)
                        //entry.Reload();    

                        //(2)
                        DbPropertyValues originalValues = entry.OriginalValues.Clone();
                        //При установке состояния объекта в Unchanged 
                        //из Deleted в OriginalValues записываются CurrentValues
                        entry.State = EntityState.Unchanged;

                        //восстанавливаем OriginalValues
                        //если объект перед удалением был модифицирован, 
                        //то восстановление OriganalValues переведет объект в состояние Modified
                        entry.OriginalValues.SetValues(originalValues);

                        if (entry.State == EntityState.Modified)
                        {
                            //При установке состояния объекта в Unchanged из Modified 
                            //в CurrentValues записываются OriginalValues
                            entry.State = EntityState.Unchanged;
                        }
                        break;

                    default:
                        break;
                }
            }
        }
     }


Далее необходимо только перечитать сущность на форму, из Model в ViewModel (автоматическое отображение во View).
Вопрос: Ссылка не указывает на экземпляр объекта

Есть класс для зашифровки и дешифровке текста
при зашифровке(GenText("Ё")) - все нормально
но при дешифровки (ReGenText("RU00S")) - выдает "Ссылка не указывает на экземпляр объекта"(строчка 43)
что делать?

P.S.
Буква "Ё" и "RU00S" - даны для примера.
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
static class DAVCONTOL
    {
        static slDV[] arraysldv = new slDV[256];
        public static void start()
        {
            byte a = 0;
            arraysldv[a] = new slDV();
            arraysldv[a].one = "RU00S";
            arraysldv[a].two = 'Ё';
        }
 
        static public string GenText(string text)
        {
            Char[] CgarS = text.ToCharArray();
            text = "";
            for (int i = 0; i < CgarS.Length;i++ ) 
            {
                for (int j = 0; i < arraysldv.Length; i++)
                {
                    if (arraysldv[j].two == CgarS[i])
                    {
                        text += arraysldv[j].one;
                        break;
                    }
                }
            }
            return text;
        }
 
        static public string ReGenText(string text)
        {
            Char[] CgarS = text.ToCharArray();
            text = "";
            string text0 = "";
            for (int j = 0; j < CgarS.Length / 5; j++)
            {
                for (int i = 0; i < 5; i++)
                {
                    text0 += CgarS[(j * 5) + i];
                }
                for (int i = 0; i < arraysldv.Length; i++)
                {
                    if (arraysldv[i].one == text0)
                    {
                        text += arraysldv[i].two;
                    }
                }
            }
                return text;
        }
    }
    class slDV
    {
        internal string one = " ";
        internal char two =' ';
    }
Добавлено через 6 часов 3 минуты
Сам повертелся покрутился нашел костыльный выход, вместо единого массива, сделал 2
Как-то так:
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
static class DAVCONTOL
    {
        static string [] ArraySymdolGen = new string [256];
        static char [] ArraySymdolReGen = new char [256];
 
        static public void start ()
        {
            byte a = 0;
            ArraySymdolGen[a] = "RU00S";
            ArraySymdolReGen[a] = 'Ё';
        }
 
        static public string GenText(string text)
        {
            Char[] CgarS = text.ToCharArray();
            text = "";
            for (int i = 0; i < CgarS.Length; i++)
            {
 
                for (int j = 0; j < ArraySymdolReGen.Length; j++)
                {
                    if (ArraySymdolReGen[j] == CgarS[i])
                    {
                        text += ArraySymdolGen[j];
                        break;
                    }
                }
 
            }
 
                return text;
        }
 
        static public string ReGenText(string text)
        {
            Char[] CgarS = text.ToCharArray();
            text = "";
            for (int i = 0; i < CgarS.Length/5; i++)
            {
                string helpText = "";
                for(int j = 0; j<5;j++)
                {
                    helpText += CgarS[(i * 5) + j];
                }
                for (int j = 0; j < ArraySymdolGen.Length; j++)
                {
                    if (helpText == ArraySymdolGen[j])
                    {
                        text += ArraySymdolReGen[j];
                        break;
                    }
                }
            }
            return text;
        }
    }
Но я всё равно не понял в чем была причина в прошлой версии =(
Ответ: Sergey84, ну как это не поняли в чем причина...
Смотрите, у Вас цикл построен от 0 до arraysldv.Length. Массив arraysldv имеет запись под индексом 0, остальные null. Когда цикл выполняется первый раз, идет обращения к нулевому индексу массива, согласно счетчику i, в котором находится класс slDV. А вот когда проходит первая итерация и счетчик имеет значение 1, при обращении к ячейке массива Вы получаете исключение, потому что под индексом от 1 до 256 в Вашем массиве ничего нет.
Вопрос: Обращение к объекту не по индексу, а по имени

Не знаю как словами описать, лучше пример приведу:
Delphi
1
2
3
4
5
6
7
8
9
10
  type
 
    TButtons = class
     Name:string;
     List:TList<TSpeedButton>;
     constructor New(NewName:string);
    end;
 
 var
   PF_Buttons:TList<TButtons>;
Смысл в том, что мы создаём класс, добавляем его в Лист PF_Buttons, в каждом классе есть список динамически созданных кнопок в "List:TList<TSpeedButton>;"

Далее идёт обращение, допустим:
Delphi
1
PF_Buttons[0].List[0].Down:=true;
Соответственно хочется обращаться не по индексу PF_Buttons[индекс], а как то по имени, т.к. индексов будет дофига, и код становится не читаемым. на много лучше, если бы было PF_Buttons[имя]. Думаю тут ничего не сделать, но может я чего то не знаю)
Ответ:
Сообщение от artyoms
почему "мало чем оправдано"?
Потому что атрибут Name уже встроен в объекты класса TComponent, равно как и поиск в списке по этому атрибуту.
Вопрос: Работа с массивом объектов или что-то в этом роде

Здравствуйте.
У меня есть цикл в котором происходит вывод таблицы с датами на 30 дней вперёд. Так же у меня есть сложный объект, в котором много различной информации. Обращение к элементам объекта выглядит так:
PHP
1
2
3
4
5
foreach($ChildHealthDay->GetChildHealthDayDataByDoctorIDResult->KeyValueOfdateTimeChildHealthDayData_SYtopWnD as $object)
{
    echo $object->Key;                                     //Выводится дата 
    echo $object->Value->AgeMax."<br>";          //Выводится число
}
Мне нужно, чтобы если среди дат, которые были выведены в таблице оказывается та, что есть в объекте, то рядом с датой вывелось ещё и число из объекта, соответствующее дате.

Я предполагаю, что разумно будет создать некий массив объектов и для каждой даты проверять входит ли она в этот массив. Погуглил, но ничего вразумительного не нашёл (наверное не так ищу). Можете набросать примерчик?
Ответ: Azdeman, да, возможно я и правда объяснил как-то не очень...
У меня есть код, который строит табличку с датами на 30 дней вперёд. На пример вот так:
PHP
1
2
3
4
5
6
7
8
echo "<TABLE border='1'>";
for($d = 0; $d < 30; $d++)
{
    $Date = date('Y-m-d', mktime(0, 0, 0, date("m"), date("d") + $d, date("Y")));
    echo "<TR align=center><TD width='5%'><b>".date_create($Date)->Format('d')."</b></TD>";
    echo "<TD width='30%'>какой-то текст</TD></TR>";
}
echo "</TABLE>";
И есть большой и сложный объект (полностью структуру не привожу т.к. она огромна, да и меня интересуют всего два поля). Достучаться до его элементов можно так:
PHP
1
2
3
4
5
foreach($ChildHealthDay->GetChildHealthDayDataByDoctorIDResult->KeyValueOfdateTimeChildHealthDayData_SYtopWnD as $object)
{
    echo $object->Key." ";                                     //Нужная мне дата 
    echo $object->Value->AgeMax."<br>";          //Нужное мне число
}
Так вот мне нужно в мою таблицу добавить число AgeMax в ячейку с соответствующей датой.
На пример у нас в результате работы цикла foreach на экран вывелось:
22.01.2016 7
29.02.2016 9
Соответственно в таблице в соответствующую строку помимо самой даты 22.01.2016 должно ещё попасть число 7.

Для этого я хотел создать массив объектов, состоящих из двух полей (датой и числом) и в цикле для каждой даты прохдиться по этому массиву и искать соответствие дат. Как это сделать? Или всё можно сделать значительно проще?
Вопрос: Обращение к конкретному экземпляру класса

Здравствуйте, столкнулся с такой проблемой.
Есть класс с простенькими методами.

через цикл создаю несколько его экземпляров.

Код Java(TM) 2 Platform Standard Edition 5.0
1
2
3
4
5
6
7
8
for(int i=0; i<10; i++){
for(int j=0; j<10;j++)
{
  RL = new RedLine();
  RL.setPosition(i*10, j*10);
  RL.draw();
}
}
т.е. создается 100 объектов класса RedLine (public RedLine RL; объявлен заранее)
Как обратиться к конкретному объекту, для возможности изменить параметры метода ? (поменять позицию)
Необходимо это для обработки собтия onClick. Проблемма в том, что изменить параметры нужно не только у того объекта, по кторому был совершен клик, но и у соседних.

Насколько разумно использовать такой подход ? Ведь при каждом создании копии объекта происходит выделение на него оперативной памяти ? Есть какие-нибудь другие подходы ?
Ответ: Зачем создавать копии уже существующих объектов?
Вопрос: Блокируется объект класса под интерфейсом

День добрый. Попытаюсь объяснить свою проблему. В программе реализован интерфейс, который описывает логику источника данных (возвращает текст и значение параметров). Пробую реализовывать под ним стандарт OPCDA. В данном стандарте создается объект (CallBack функция), ссылка на который передается внешнему OPC-серверу, который вызывает эту функцию при изменении параметров. Получается так, что внешний OPC сервер не может вызвать эту функцию, поскольку она блокирована интерфейсом для монопольного доступа. Можно ли как то создавать объект класса за интерфейсом, который был бы доступен и другим потокам? Путанно объяснил но как то так. Если просто делать класс с обращением по OPC то все нормально, внешний OPC сервер CallBack функцию вызывает и данные обновляются. Но если к объекту класса ссылаться через интерфейс, то CallBack функция не отрабатывает, пока ссылка интерфейса не осободится.
Ответ: Нашел решение. Надо перед работой с COM объектами вызвать:

Код:

CoInitializeEx(nil, COINIT_MULTITHREADED);

Раньше было:

Код:

CoInitialize(nil);