-
Делаю редактор с подсветкой кода. Так вот после каждого нажатия клавишы должен запускаться фоновый поток - стилист. Он должен распарить строки. После этого он может спать спокойно, специально его усыпляю что-бы не ел ресурсы
procedure TForm1.SetReStyle(const Value: Boolean);
begin
FReStyle := Value;
if Value=True then
begin
StyleTimer.Enabled:=True;
Stylist.Resume;
end else
begin
StyleTimer.Enabled:=False;
Stylist.Suspend;
end;
end;
procedure TStylist.Execute;
var LIndex:Integer;
const NegOne:integer=-1;
begin
while not Terminated do
begin
LIndex:=InterlockedExchange(Index, NegOne);
if LIndex<>-1 then
begin
FIsWork:=True;
DoWork(LIndex);
inc(LIndex);
end else
begin
FIsWork:=False;
end;
if LIndex>StringList.Count then
begin
FIsWork:=False;
end;
InterlockedCompareExchange(Pointer(Index), Pointer(NegOne), Pointer(LIndex));
end;
end;
Index -это общая переменная как следствие она подлежит защите, её строю на атомарных операциях. Но вот беда мне ещё надо обезопасить общий массив строк. Это должно происходить почти одновременно с Index Собственно как это лучше сделать? Неужели придётся использовать Mutex и методы Lock, unLock или есть более лучшее решение которое позволит уменьшить связность классов?
-
Давайте тогда поставим вопрос по другому. Как улучшить качество такого кода?
procedure TStylist.DoWork(Index: Integer); var Plexma:TPlex; LineState:TLineState; Count:Integer; begin try Lock; Count:=Lines.Count; UnLock; if (0<=Index) and (Index<Count) then begin Lock; LineState:=Lines.Objects[Index] as TLineState; LineState.Row:=Index; Plexer.LoadState(LineState, nil); UnLock; repeat Plexma:=Plexer.ReadPlexTeg; until( pkEol in Plexma.Kind) or ( pkEoF in Plexma.Kind) or Terminated; Lock; if Index+1<Lines.count then begin LineState:=Lines.Objects[Index+1] as TLineState; LineState.PlexKind:=Plexma.Kind; end; UnLock; end; except end; end;
procedure TStylist.Execute; var LIndex:Integer; const NegOne:integer=-1; begin while not Terminated do begin LIndex:=InterlockedExchange(Index, NegOne); if (LIndex<>-1) then begin FIsWork:=True; DoWork(LIndex); inc(LIndex); end else begin FIsWork:=False; end; if LIndex>Lines.Count then begin FIsWork:=False; LIndex:=-1; end; InterlockedCompareExchange(Pointer(index),Pointer(LIndex), Pointer(NegOne)); end; end;
-
Lock/Unlock выкинуть. Вход в критическую секцию. Смысл работы в потоках пропадает. Если обращение к другому VCL-классу, лучше вызвать процедуру через Synchronize. Хотя там тоже вход в крит. секцию.
-
Когда я делал редактор с подсветкой кода, то тоже сначала думал про многопоточность и синхронизацию, а потом на это забил, и сделал всё в основном потоке. Производительности современных машин вполне хватает, чтобы успеть распарсить до нескольких десятков строк, которые могут поменять подстветку при вводе.
-
> Dimka Maslov © (10.03.18 11:46) [3]
согласен. да и продуманный алгоритм не требует распарсивания всего постоянно.
-
> Pavia © (06.03.18 15:16) > > Делаю редактор с подсветкой кода
> Dimka Maslov © (10.03.18 11:46) [3] > > Когда я делал редактор с подсветкой кода,
И где ваши редакторы? Есть в открытом доступе посмотреть? Я тоже сейчас вроде как дописываю. Но у меня тоже все в основном потоке, смысла делать по другому не вижу.
-
> . Производительности современных машин вполне хватает, чтобы > успеть распарсить до нескольких десятков строк, которые > могут поменять подстветку при вводе.
Тут наверное другое. Автор наверное озадачился вопросом сброса сканера и его перезапуска после изменения текста. Так? Так что производительность тут не причем.
-
> Есть в открытом доступе посмотреть?
К сожалению, нет.
-
> К сожалению, нет.
Я не исходники имел ввиду, может вы не правильно поняли
-
> aka © (10.03.18 22:14) [8]
мой и без исходников не посмотреть. только купив оборудование, к которому он прилагается.
-
> aka © (10.03.18 22:14) [8]
Это продукт для внутреннего потребления.
-
Ясно
-
Сама задача/цель недостаточно ясна. Нужно подробнее. И да, чем именно обусловлена необходимость в отдельном потоке?
-
> Lock/Unlock выкинуть. Вход в критическую секцию. Смысл работы > в потоках пропадает.
Тут просто фоновая задача. Пока основной поток спит фоновый работает. Хотя конечно мне они сами не нравятся.
> Если обращение к другому VCL-классу, лучше вызвать процедуру > через Synchronize. Хотя там тоже вход в крит. секцию.
Synchronize построен на очереди сообщений. Это будет медленно.
Возможно TEvent будет лучше?
> чтобы успеть распарсить до нескольких десятков строк, которые > могут поменять подстветку при вводе.
Кавычку поставил и подсветка меняется сразу во всём файле. Есть скролинг с возможностью переброса на нужную линию. Как бы есть файлы по 10 000 строк и более. Парсер у меня довольно медленный несколько тысяч в секунду. 0,1 с не более 1000 строк.
> Автор наверное озадачился вопросом сброса сканера и его > перезапуска после изменения текста. Так? Так что производительность > тут не причем.
Да именно так. Человек может делать до 10 ударов в секунду 600 ударов в минуту или 1 удар за 0,1 секунду. Парсер может работать более 0,1 секунды. Поэтому его надо остановить и запустить заново.
> Сама задача/цель недостаточно ясна. Нужно подробнее.И да, > чем именно обусловлена необходимость в отдельном потоке?
Рекомендациям диванных теоретиков на разных форумах. Во вторых мне просто было интересно сделать это через потоки.
Поначалу задачка кажется простой. Человек нажал клавишу и запустился фоновый поток. Но потом возникают общие данные которые требуют защиты поэтому использую Lock и UnLock. Есть вариант сделать дублирование данных, но даже в этом случае Lock и UnLock останутся.
Но это не всё оказывается, что фоновый поток должен получать команды от основного. На запуск повторного сканирования. Очередь сообщений не хочу, так как она имеет свойство переполняться да и ждать завершения тоже не могу, так как задержка результата будет накапливаться - пользователю будет неудобно. Как вариант решения проверять наличие нового задания после разбора каждой линии. Разбор линии много меньше скорости нажатия клавиш. Даже если он будет больше, то ничего страшного.
-
-
> Человек может делать до 10 ударов в секунду 600 ударов в > минуту или 1 удар за 0,1 секунду.
Да, может. Вот только есть два нюанса - это довольно-таки редкий человек, и в таком режиме ему подсветка пофиг.
-
> Кавычку поставил и подсветка меняется сразу во всём файле. а зачем? любой символ влияет на слово до, слово после, и все, + при вставке копипастом слово до нее, слово после и сам текст копипаста. зачем во всем файле?
или, можно сделать "универсально" свою отрисовку "окна"(т.е. только видимой части) с учетом подсветки, тогда размер текста/вставки, или методы изменения перестанут иметь значение... вот тут делал, не подсветку, свое (типа мониторинга видимой части), но и про редактор на этом принципе думал... подходит.
> Парсер может работать более 0,1 секунды. да брось, за 0,1 сек. "можно добежать до канадской границы" не то, что пару слов со списком сравнить.
p.s. поток не нужен, критическая секция как следствие тоже.
-
-
> Да, может. Вот только есть два нюанса - это довольно-таки > редкий человек, и в таком режиме ему подсветка пофиг.
Наоборот он смотрит на экран, а не на клавиши. Даже более того 0,1 с это медленно так что я думаю уменьшить интервал таймера до 0,05
> а зачем? любой символ влияет на слово до, слово после, и > все, + при вставке копипастом слово до нее, слово после > и сам текст копипаста. зачем во всем файле?
Вы строки никогда не видели? Ставите кавычку и цвет меняется у всех слов пока он не встретит пару. Но если у вас было чётное число кавычек, а стало нечётное то все участки должны инвертироваться. Но так как ковычек вернее групповых операторов более 3 то сохрнаить в виде одного бита невозможно. Нужно пере разбирать весь файл.
-
Far colorer - rulezz fareva С исходниками даже
-
> Наоборот он смотрит на экран, а не на клавиши. Даже более > того 0,1 с это медленно так что я думаю уменьшить интервал > таймера до 0,05
Да, смотрит. На одну страницу экрана, а точнее, на то место, что набирает. И форматирование пофиг, 600 знаков в минуту - это скорость машинистки.
> Ставите кавычку и цвет меняется у всех слов пока он не встретит > пару. Но если у вас было чётное число кавычек, а стало нечётное > то все участки должны инвертироваться. Но так как ковычек > вернее групповых операторов более 3 то сохрнаить в виде > одного бита невозможно. Нужно пере разбирать весь файл.
неверный подход. а) Инвертироваться должны не все участки, а только отрисовываемые в данный момент б) один раз отпарсив весь файл можно получить полную структуру, ее изменение в любом месте позволяет вычислить последствия без нового парсинга, а учитывая а) - очень быстро.
|