![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
ISAPI(dll) разделение общих ресурсов в копиях dll [D7, WinXP]
piople © (2006-03-20 14:35:00)Доброго времени суток!
Вообщем разрабатываю сайт с использованием ISAPI, все замечательно, но столкнулся с такой проблемой - это общие ресурсы для всех копий dll, то есть, например, запросил пользователь некую страничку, берутся данные обрабатываются и в конечном итоге передаются клиенту... но, потом эти даннные по прежднему остаются в памяти, и при следующей запросе получается дублирование данных...
Детально:
некто запросил: babah.ru -> выполняется скрипт и результат помещается в некую переменную TMPVar-> результат скрипта отправлен пользователю...
следующий пользователь (либо паралельно с первым) выполняет запрос туда же: babah.ru -> выполняется скрипт и результат помещается в некую переменную и тут калапс, получается что в переменной хранятся старые данные и новые!!!-> пользователю уходят ненужные данные...
Казалось бы парень просто обнуляй переменную и все!!! Не хочет все равно... если допустим у меня цикл в моей dll который работает с TStringList и делает в него добавление данных (ADD) и тут же кто-то другой тоже далет запрос туда же (вернее хоть куда где использутеся мой TStringList) то он добавляет данные В ТОТ ЖЕ DLL!
Не знаю что делать... пытался копать в сторону:
const
COINIT_MULTITHREADED = 0;
COINIT_APARTMENTTHREADED = 2;
function CoInitializeEx(pvReserved: pointer; coInit:
Longint): HResult; stdcall;
Параметр pvReserved зарезервирован для будущего использования и должен быть всегда равен nil, а параметр coInit определяет модель потоков создаваемого апартамента. Он может принимать значения COINIT_APARTMENTTHREADED и COINIT_MULTITHREADED. В первом случае для потока создается однопоточный апартамент, причем каждый поток может иметь, а может и не иметь свой апартамент. Во втором случае, если в текущем процессе еще не создан многопоточный апартамент, он создается. Если же многопоточный апартамент уже создан другим потоком, текущий поток подключается к готовому апартаменту. Другими словами, каждый процесс может иметь только один многопоточный апартамент. Вышеописанная функция возвращает значение S_OK в случае успешного создания апартамента. Каждому вызову CoInitializeEx должен соответствовать вызов CoUninitialize. То есть, если вы работаете с СОМ в приложении, функция CoInitializeEx должна быть вызвана до первого вызова функций СОМ, а CoUninitialize должна быть вызвана по завершении работы приложения. По завершении работы с СОМ (или перед завершением работы) поток должен уничтожить апартамент путем вызова процедуры CoUninitialize. Библиотека VCL выполняет автоматическую инициализацию СОМ при использовании модуля ComObj, и по умолчанию создается однопоточный апартамент. Если вам в приложении необходима другая модель потоков, следует внести исправления в файл проекта *.dpr, установив флаг инициализации СОМ до оператора Application.Initialize:
program Project1;
uses
Forms, ComObj, ActiveX,
Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}
begin
CoInitFlags := COINIT_MULTITHREADED;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end;
к сожалению ничего не нашел...
Сергей М. (2006-03-22 12:33:00) [1]
> WondeRu © (22.03.06 12:13) [17]
Потому что память под эту указательную переменную действительно выделяется в TLS текущего потока, а вот память под объект, на который впоследствии будет указывать эта переменная, выделяется уже не в TLS, а в куче.
WondeRu (2006-03-22 12:13:00) [2]Сергей М. © (22.03.06 12:12) [16]
SL: TStringList; // SL по сути и есть Pointer
сам же написал... почему, Сергей, это другое?
Сергей М. (2006-03-22 12:12:00) [3]
> WondeRu © (22.03.06 11:50) [15]
Это несколько из другой оперы.
Убедись, что следующий код успешно работает:
threadvar
SL: TStringList; // SL по сути и есть Pointer
type
TMyThread = class(TThread)
private
FNum: Integer;
FList: TStrings;
procedure ShowList;
protected
procedure Execute; override;
constructor Create(ThreadNum: Integer);
end;
{ TMyThread }
constructor TMyThread.Create(ThreadNum: Integer);
begin
FNum := ThreadNum;
inherited Create(False);
end;
procedure TMyThread.Execute;
var
i: Integer;
begin
FreeOnTerminate := True;
FList := TStringList.Create;
SL:= TStringList.Create;
for i:= FNum to FNum + 50 do
SL.Add(IntToStr(i));
FList.Assign(SL);
Synchronize(ShowList);
SL.Free;
FList.Free;
end;
procedure TMyThread.ShowList;
var
i: Integer;
begin
for i:= 0 to FList.Count - 1 do
Form1.Memo1.Lines.Add('ThreadNum = ' + IntToStr(FNum) + ' StringList[' + IntToStr(i) + '] = ' + FList[i]);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
TMyThread.Create(1);
TMyThread.Create(2);
end;
WondeRu (2006-03-22 11:50:00) [4]The threadvar section can only be used for global variables. Pointer and Function variables can't be thread variables.Types that use copy-on-write semantics, such as long strings don't work as thread variables either.
Сергей М. (2006-03-22 10:59:00) [5]threadvar
Myvar: TStrings;
В событии BeforeDispatch:
Myvar := TStringsList.Create;
В событии AfterDispatch:
FreeAndNil(Myvar);
Сергей М. (2006-03-22 10:50:00) [6]
> piople © (22.03.06 09:40) [12]
Все равно мне не понятно, почему вариант с глобальной threadvar-переменной не проходит .. Обязан проходить !
piople (2006-03-22 09:40:00) [7]К сожалению данные метод не реализуем в моей функции, так как я еще использую TPageProducer и у него свои процедуры/функции использующие те же стринглисты... :(
Сергей М. (2006-03-21 12:50:00) [8]см. событие TWebActionItem.OnAction
в его обработчике :
var TMPVar: TStringList;
begin
TMPVar := TStringList.Create;
try
... обрабатываешь акцию
finally
TMPVar.Free;
end;
end;
piople (2006-03-21 12:31:00) [9]Создал...
procedure TWebModule1.WebModuleCreate(Sender: TObject);
begin
....
news := TStringList.create; //Новостная лента
MainS := TStringList.Create; //Тело форума
Top10 := TStringList.Create; //10 последних сообщений
...
end;
Убил...
procedure TWebModule1.WebModuleDestroy(Sender: TObject);
begin
news.Free;
MainS.Free;
Top10.Free;
end;
Сергей М. (2006-03-21 11:31:00) [10]А где конструируешь-разрушаешь эттот объект ?
piople (2006-03-21 11:14:00) [11]
> unit main;
>
> interface
>
> uses
> SysUtils, Classes, HTTPApp, DB, ADODB, HTTPProd, DBWeb,
> DBBdeWeb, StrUtils, windows,
> mshtml, activex, OleCtrls, SHDocVw, variants, StdCtrls,
> Math;
>
> type
> TWebModule1 = class(TWebModule)
> Tmpl: TPageProducer;
> Query: TADOQuery;
> DQuery: TADOQuery;
> ADOConnection: TADOConnection;
> ADOCommand: TADOCommand;
>
> { Private declarations }
> public
>
> { Public declarations }
> end;
>
> var
> WebModule1: TWebModule1;
> MainS, news, Top10 : TStringList; ВОТ ТУТ :)
>
> implementation
>
> uses Dialogs, DateUtils;
>
> {$R *.dfm}
Сергей М. (2006-03-21 09:36:00) [12]
> piople © (21.03.06 09:32) [6]
> объявлен в общем VAR
Гдеобъявлена-то ?
Статическая это переменная или локальная ?
piople (2006-03-21 09:32:00) [13]TMPVar это мой TStringList объявлен в общем VAR...
Сергей М. (2006-03-21 08:49:00) [14]Ну где у тебя эта самая TMPVar объявлена ?
piople (2006-03-21 05:38:00) [15]хе... думаю многовато будет...
Что именно мне надо представить? Это обычный ISAPI...
Сергей М. (2006-03-20 15:56:00) [16]Приводи код
piople (2006-03-20 15:16:00) [17]К сожалению результат тот же...
Сергей М. (2006-03-20 14:58:00) [18]
> в некую переменную TMPVar
library MyISAPIlib;
...
threadvar
TMPVar: SomeType;
begin
..
IsMultiThread := True;
..
end.