-
Всем привет. Использую Rad 2009, ODAC 6.90.0.55.
Сабж:
Клиент подключается к программе через TCP/IP. Если клиент начинает посылать данные, то идет вызов процедуры Oracle с этими данными, которая возвращает данные для отправки клиенту обратно. Когда подключается один клиент - проблем нет. А вот когда больше одно, то получается следующее: процедура выполняется, и вдруг ещё один пользователь отправил данные. Процедура, которая выполнялась останавливается и начинает выполняться новая. Клиент, который запустил её первый - ничего не получает. Как тут можно поступить? Создать массив из компонентов TOraStoredProc и создавать в нём компоненты при подключении. Каждое соединение будет использовать свой компонент. Или же определять запущено ли выполнение процедуры и подождать, когда завершиться.
Подскажите, пож-та. Спасибо.
-
А что логика приложения требует?
Процедура что, имеет жесткий параметр(нет параметра)?
И каждый запускает только с ним?
-
Параметры тут не при чем. Если идет выполнение процедуры и вдруг её опять вызывают, то он останавливает выполнение и возвращает, что есть. Это наверное все компненты для работы с базами данными так делают. Вот я и спрашиваю делать много компонентов(для каждого компонента свой TOraStoredProc) или как?
-
В общем случае - да.
Делай как oracle сам делает: на запрос от клиента процесс-Listener выделяет новый поток (или берет свободный из пула потоков) и назначает его этому клиенту. Больше листенер клиенту не нужен.
Представим, что твоя программа Listener.
Клиент соединяется с программой, программа рождает для него поток, в котором есть все компанеты доступа(_свой_ TOraSession, TOraStoredProc, etc ), связывает клиента с этим потоком, и забывает про этого клиента.
-
Спасибо, большое. Подскажите, пожалуйста, как сделать вышеописанное вами.
Пытался сделать через массив форм. На каждой форме есть сессия и процедура. Вроде работает, но приложение виснет, пока клиенты не отключаться.
-
Не через формы
Через список потоков
> Вроде работает, но приложение виснет
потому что все в одном потоке, главном, VCL
На новое соединение создается и запускается класс-наследник TThread
-
Спасибо. Буду читать про потоки в Windows и Delphi.
Потом отпишусь.
-
Подскажите еще, пожалуйста. Обязательно для каждого нового соединения создавать сессию в Oracle. Нельзя через одну сессию делать много ToraStoredProc?
-
> Обязательно для каждого нового соединения создавать сессию
> в Oracle
Если в разных потоках - да
-
Добрый вечер.
Начал пробовать с потоками.
Создаю класс-наследник.
type
TOraThread = class(TThread)
private
OraSession: TOraSession;
OraProc: TOraStoredProc;
protected
procedure Execute; override;
public
function Connect(pOraConnectString: String): Boolean;
procedure Disconnect;
end;
Методы:
function TOraThread.Connect(pOraConnectString: String): Boolean;
begin
Result := False;
if OraSession.Connected then
Result := True
else
try
OraSession := TOraSession.Create(nil);
OraSession.ConnectString := pOraConnectString;
OraSession.LoginPrompt := False;
OraSession.Connect;
Result := True;
except
end;
end;
procedure TOraThread.Disconnect;
begin
if OraSession.Connected then
OraSession.Disconnect;
end;
Как создаю:
var
OraThreads: Array[1..10] of TOraThread;
...
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
for i := 1 to SpinEdit1.Value do
begin
Inc(OraThreadsCount);
OraThreads[i].Create(True);
OraThreads[i].Connect(OraSession1.ConnectString);
end;
end;
При нажатии на кнопку получаю EAccessViolation. Подскажите, пожалуйста, что я делаю не так? Спасибо!!!
-
что то не создано в момент вызова, вот хоть сессия т.к делается "внешним" вызовом извне потока, и в момент работы потока... скорее всего, т.к. что то после нее или в ней не видно resume... т.е. оно где то в "не опубликованном".
-
вообще, это весь код? глюков немеряно...
1 создание потока в режиме саспенд, резюма не видно.
2 обращение к не созданому еще объекту if OraSession.Connected then
3 сессия сама по себе, ни сч чем не связана.
4 дисконект тоже бесполезная функция
-
> function TOraThread.Connect(pOraConnectString: String):
> Boolean;
> begin
> Result := False;
> if OraSession.Connected then // тут я появился :), т.к. OraSession = nil
> function TOraThread.Connect(pOraConnectString: String):
> Boolean;
> begin
> Result := False;
if OraSession <> nil then
b
> if OraSession.Connected then
Result := True
e
else
try
OraSession := TOraSession.Create(nil);
OraSession.ConnectString := pOraConnectString;
OraSession.LoginPrompt := False;
OraSession.Connect;
Result := True;
except
//
end;
-
Исправил. Тоже самое.
Возможно нужно добавить этот в код в код создания потока?
Нужно переопределить метод Create? Так же как метод Execute?
function TOraThread.Connect(pOraConnectString: String): Boolean;
begin
Result := False;
if OraSession <> nil then
Result := True
else
try
OraSession := TOraSession.Create(nil);
OraSession.ConnectString := pOraConnectString;
OraSession.LoginPrompt := False;
OraSession.Connect;
Result := True;
except
end;
end;
-
> Возможно нужно добавить этот в код в код создания потока?
> Нужно переопределить метод Create? Так же как метод Execute?
это все равно
Когда поток стартует? где resume?
Как используется, короче?
-
> вообще, это весь код? глюков немеряно...
> 1 создание потока в режиме саспенд, резюма не видно.
> 3 сессия сама по себе, ни сч чем не связана.
> 4 дисконект тоже бесполезная функция
Это весь код, для начала пытаюсь проверить как создавать потоки с сессиями.
Потом буду внедрять в прогу.
1. Хочу просто создать сессию ничего не делая.
3. А с чем нужно связать?
4. Почему бесполезно? При уничтожении потока будет выполнен корректное отключение от базы данных?
-
Надо запустить поток, чтобы сессия создалась?
-
Исправил. К сожалению ситуация не изменилась.
OraThreads[i].Create(False);
-
> Это весь код
это очень мало...
> Надо запустить поток, чтобы сессия создалась?
смысл потока в том чтобы его "запускать" и выполнять в нем какие то действия, без этого, используя его исключительно как контейнер для функций, он бесполезен. однозначно.
> Исправил. К сожалению ситуация не изменилась.
значит не там исправил.
-
> 4. Почему бесполезно?
не используется. раз - "Это весь код"
> При уничтожении потока будет выполнен корректное отключение от базы данных?
это ты у меня спрашиваешь? код твой! сделаешь - будет, нет - ну и не надо...
-
Сделал все по новой. Вроде работает.
Только подскажите пож-та, когда вызывается метод потока Execute?
Если он запускается циклически, то с какой периодичностью?
Спасибо.
-
справочная информация находится в справке.
-
> когда вызывается метод потока Execute?
ОС решает, зависит от приоритета процесса, потока,
других запущенных на компе потоков/процессов,
в т.ч. системных
-
-
Спасибо, большое!
-
А еще вопросик.
Смотрите, при подключении клиента к IdTCPServer инди делает новый поток, нельзя ли как-то создать в этом потоке нужные мне данные(OraSession, и т.д.).
А то получается для соединения инди делает поток, потом еще я делаю поток. Не будет проблем при вызове процедур моих потоков из потока инди?
-
> Смотрите, при подключении клиента к IdTCPServer инди делает
> новый поток, нельзя ли как-то создать в этом потоке нужные
> мне данные(OraSession, и т.д.).
Я создавал на событие соединения свой поток со своим IdPerThread, в качестве переменной,
которой просто присваивал порожденный из IdTCPServer поток
т.о. в моем потоке содержится поток от инди