Немножко вне рутины...
Немножко вне рутины...
</p><blockquote style=""> using System; using System.IO; using System.Collections.Generic; using System.Linq; using System.Text; namespace A { class A { StreamWriter sw = null; public StreamWriter Sw { get { if(sw == null) { // get from class where instantiated/specified. } return sw; } set { sw = value; } } } class B1 : A { String b1 = "B1"; public void GetResult() { Sw.Write(b1); B2 b2 = new B2(); b2.GetResult(); } } class B2 : A { String b2 = "B2"; public void GetResult() { Sw.Write(b2); } } class Program { static void Main(string[] args) { using (StreamWriter sw = new StreamWriter("Data.dat")) { B1 b1 = new B1(); b1.Sw = sw; b1.GetResult(); } } } } </blockquote><p>
Что имеем? Имеем один базовый класс А и несчетное множество производных B*.
Существенно - классы B* между собой НЕ взаимодействуют - нет пересылки данных или передачи параметров, но один класс может инстанцировать другой и вызывать методы другого.
Классы B* выполняют какие-то действия (какие - не суть важно) и помещают результат в stream. Вид stream'а и что именно туда скидывается меня не интересует.
Меня интересует - можно ли в приведенном коде обеспечить чтобы B1 & B2 использовали один и тот же stream?
Чтобы было не слишком легко - несколько Б*шек будут работать параллельно - одним стреамом обойтись не получится - мне нужен именно доступ к тому где он задаn...
Существенно - классы B* между собой НЕ взаимодействуют - нет пересылки данных или передачи параметров, но один класс может инстанцировать другой и вызывать методы другого.
Что-то я не понял, если классы B* между собой не взаимодействуют, то как один класс может инстанциировать другой и вызывать его методы?
Меня интересует - можно ли в приведенном коде обеспечить чтобы B1 & B2 использовали один и тот же stream?
Чтобы было не слишком легко - несколько Б*шек будут работать параллельно - одним стреамом обойтись не получится - мне нужен именно доступ к тому где он задаn...
Делаешь фабрику стримов и пусть она принимает решение о том, создать новый стрим или вернуть один из существующих.
Ответ, по-моему, очевиден: нет.
-----
Хммм... Я бы не был столь категоричен.
Или скажем по-другому - мне нельзя быть столь категоричным. Просто потому, что надо сделать.
Одним из вариантов решения будет сделать поток статическим. Но этот вариант меня не устраивает,
т.к. пора перебираться из однопоточной задачи в многопоточную.
Надо придумать что-то типа треад-статик вариабле... Что на 100% возможно.
Но там получается другая (см. внизу) сложность.
Изначально это делается чтобы сократить издержки на создание стреамов. Они - неприемлемо высокие.
Первоначально Я сделал пулл потоков и подставлял стреам из пула когда его запрашивали.
Относительно начальной схемы, где стреамы создавалось локально, все существенно ускорилось.
Пулл был рамером в 120 стреамов. Больше 240 - не выдерживала ОСь. Возможно, что можно что-то
подстроить (см Филес в конфиге), но проблема не в этом - там была однозадачная система. А мне сейчас
нужно иметь параллельность выполнения. При параллельном выполнении количество задействованных
стреамов очень быстро достигнет предела. Каким бы предел ни был. Т.е. это не вариант.
Так что остается только контролировать количество исполняемых треадов и гарантировать что
в треаде используется один стреам. И этот стреам надо как-то шарить между Бешками.
А упомянутая выше сложность заключается в том, что треад не умеет (ну или Я не умею) возвратить
стреам в пулл по завершении потока. А создавать его каждый раз внутри потока - накладно...
если ... то
-----
Ну давай напишем - ограниченно взаимодействуют - могут вызвать единственный хорошо известный метод без параметров.
Ничего добавить Я не могу - Бешки - не рукотворные и имеют жесткие ограничения.
А самое главное - очень не хочется иметь что-то более сложное - они будут создаваться и отдаваться фабрикой как имплементация интерфейса с одной функцией. Кто и как сделал вызов - мне, на момент написания, будет неизвестно.
Чтобы было совсем весело - подозреваю, что мне еще и инстансы Бешек надо будет кешировать...
Делаешь фабрику стримов
-----
У меня есть пулл стреамов.
Потому что создавать их дорого.
Но пулл, к сожалению, не может принимать подобные решения.
Можно написать менеджера.
Примерно так, как сделано в Main - b1.Sw = sw; - но это - внешнее управление.
Мне нужно, чтобы эту задачу решал код в инстансе А, который "НЕ знает" кто пытается получить доступ к стреаму, но "знает", при отсутствии стреама инстанциация производится где-то внутри метода другой Бешки у которой есть нужный стреам. Вот до него мне и надо добраться.
Как-то так.
Существенно - классы B* между собой НЕ взаимодействуют - нет пересылки данных или передачи параметров,
Говорит о том, что реализация классов тебе не доступна, иначе почему бы GetResult не изменить так, чтобы он принимал в качестве аргумента поток, или передать его через конструктор.
А
public StreamWriter Sw { get { if (sw == null) { // get from class where instantiated/specified. } return sw; } set { sw = value; } }
исключает контроль над используемым потоком: неизвестно как и откуда getter берет поток, а setter вообще позволяет вызывающему коду подсунуть свой.
реализация классов тебе не доступна
-----
Доступна, но изменять ее Я хоть и не не могу, но очень сильно не хочу.
Бишки - классы генерируемые для Т4-шаблонов - т.е. при крайней необходимости добавить - можно, но это ручная работа и делать ее не хочется.
почему бы GetResult не изменить так, чтобы он принимал в качестве аргумента поток, или передать его через конструктор.
-----
Потому что, во-первых, именно этот метод - метод который можно вызывать - генерируется компилятором шаблонов.
А во вторых - надо будет каждый раз помнить об параметре... в том месте где Я пытаюсь освободится от какой-либо передачи параметров.
неизвестно как и откуда getter берет поток
-----
КАК - неизвестно - это и есть мой вопрос, а ОТКУДА - вполне известно - это тот же поток, который передан Б1 и лежит в его инстансе. Вопрос - как добраться до этого инстанса в указанных ограничениях?
В принципе... вроде должно получится так - добавить в базовый класс еще один метод и при вызове этого метода... нее, опять не пойдет... Ладушки - сегодня думать уже нечем - пора отдыхать...
Вы всегда странным образом формулируете Вашу проблему. Вы уже вроде бы как и решение придумали, и считаете, что нужно решить именно так.
Но не лучше ли было бы без никакого описания Вашего "дизайна", который Вы не можете заставить работать, описать просто и понятно Вашу изначальную проблему? Думаю, если Вам удастся ее четко сформулировать, то и решение Вы сами увидите тотчас. Или кто-то из публики его сможет Вам подсказать.
Вам нужно создать thread safe stream, или что-то еще?
надо будет каждый раз помнить об параметре
Без изменения архитектуры будешь только заниматься изготовлением костылей. Очень нехорошо передавать поток через проперть.
Даже имена и то странные - void метод начинается с "Гет".
А пока следующее предложение.
Делаем "потоковый записыватель" с очередью заданий. Туда поступают "Бэшки" в требуемом порядке записи (накидал и "забыл"). Затем Бэшки выбираеются из очереди и передаеются врапперу записи, который может залочить поток и записать Бэшку в поток. И так повторяется пока все Бэшки в очереди не закончатся.
Ну а как паралелить записыватели - нужно знать задачу.
Туда поступают "Бэшки" в требуемом порядке записи
-----
Если бы Я мог перевести все в список - вопрос бы не возникал.
Пока же получается так - надо записать часть из А, затем записать Б, в Б может быть инстанцировано и выполнено С, затем снова фрагмент Б и в конце еще фрагмент А.
Изменить порядок вызовов или сегментации - увы, не дано...
Даже имена и то странные - void метод начинается с "Гет".
-----
Ну писал на коленке, т.е. непосредственно на Германке - мог и ошибит'ся.
Поменял пока так:
using System;using System.IO;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace ThreadStaticTest{class A{[ThreadStatic]static StreamWriter sw = null;public StreamWriter Sw{get{if (sw == null){// get from class where instantiated/specified.throw new Exception("Output stream is null or not specified.");}return sw;}set { sw = value; }}}class B1 : A{String b1 = "B1";public void GetResult(){Sw.Write(b1);B2 b2 = new B2();b2.GetResult();}}class B2 : A{String b2 = "B2";public void GetResult(){Sw.Write(b2);}}class Process{static int threads = 1;public void Execute(){Thread newThread = new Thread(new ThreadStart(this.Generate));newThread.Name = threads.ToString();newThread.Start();}private void Generate(){using (StreamWriter sw = new StreamWriter("Data_" + threads.ToString() + ".dat")){B1 b1 = new B1();b1.Sw = sw;b1.GetResult();}}}class Program{static void Main(string[] args){Thread.CurrentThread.Name = "Main";Process p = new Process();p.Execute();}}}
Вроде работает. По крайней мере по ексептиону пока не вылетает.
Многопоточку - пока не гонял - надо сделать более-мение нормальный "источник" инстансов Б1 и прикрутить пулл для стреамов.
Будут какие замечания/пожелания/советы?
Вы всегда странным образом формулируете Вашу проблему.
------
Ну что тут поделать - Я таки ДУМАЮ странным образом. Ну а как думаю - так и формулирую.
Я знаю, что думать так как думаю Я - довольно сложно... но(!), как показывает практика, довольно эффективно.
По крайней мере, когда так думает команда - все получается довольно гладко...
Вы уже вроде бы как и решение придумали, и считаете, что нужно решить именно так.
-----
Замени "нужно" на "можно" и Я с тобою соглашусь.
Вам нужно создать thread safe stream, или что-то еще?
-----
Мне нужно шарить стреаm между объектами создаваемыми в потоке. Пока - в том же потоке.
Но вполне возможно, что все сильно-сильно ухудшится и мне нужно будет шарить стреам из внешнего, по отношению к потоку выполнения, пула в пределах потока выполнения между объектами создаваемыми в другом/других потоках.
Понимаю, что звучит сложно и неприятно - но, увы, более внятно пока не формулируется.
Если каждый пишет когда хочет, то в файле или бардак или множество мелких записей.
-----
Каждый пишет когда его "очередь" писать.
class B1 : A { String b1 = "B1"; public void GetResult() { Sw.Write(b1 + " 1"); // pishem B2 b2 = new B2(); b2.GetResult(); // pishem drugoe Sw.Write(b1 + " 2"); // snova pishem } }
Нормально там все пишется. Пока по крайней мере проблем не видел.
Что меня сейчас интересует - как это будет работать в случае когда класс инстанцируется в другом потоке... Жаль - времени потестить нет - снова надо монстром заниматься...
то есть обе строки в другом месте и ты туда не хочешь/не можешь передать поток?
-----
IB2 b2 = Program.Factory.Create("B2"); // nado napisat' b2.GetResult(); // pishem drugoe
И Я не хочу передавать туда поток в ручную - слишком много раз это надо делать и это совершенно никак не относится к решаемой этим кодом задаче.
Но Я хочу, чтобы b2.GetResult() получила доступ к стреаму в потоке выполнения и сделала это без дополнительных телодвижений с моей стороны.
Желательно - и без больших накладных расходов.
У меня вообще есть желание видеть это в одну строку. Примерно так
GetResult("B2");
Возможно, что это и будет решением.
П.С. Как-то оно близко коррелирует с твоими запросами к загрузке плагинов.
Предлагаю переименовать метод getresult() в getSUPERresult(), и все сразу пойдет : )
Это очень важно: назвать метод/переменную так, чтобы ни один шпион не догадался, что там и почему. Назвать класс "Process", и дать ему метод "Execute" (или как там?) - тоже хороший ход, как и назвать использование DLL'ов "плигином". Ребята, извините, но похоже, Вы тут только двое друг друга и понять можете ("неординарно мыслите"). Только зачем форум грузить?
как и назвать использование DLL'ов "плигином"
Можно назвать и "динамически загружаемые объекты", но все же
https://msdn.microsoft.com/en-us/library/ms972962.aspx
Да и название не играет в данном случае большой роли, сама проблема более интересна, хотя да не всем.
Только зачем форум грузить?
Мне кажется коллективная работа всегда интересней индивидуальной, да и в последнее время почти ничего нового и нет.
Неужели задачки не интересно порешать?
Как-то оно близко коррелирует с твоими запросами к загрузке плагинов.
Особой корреляции не вижу, кроме вопроса со стороны "а нахрена это всё нужно"
и это совершенно никак не относится к решаемой этим кодом задаче.
Код то производит запись в поток, значит как раз то очень и относится.
Можно переписать немного по другому
GetResult("B2"); --> writer.StoreData(typeof(B2));
Где writer не поток а твой класс, а каждая Бэшка реализует интерфейс IStoreData
Только зачем форум грузить?
------
Хммм... А зачем же форум существует? Чтобы в него НЕ писать?
Мне вот почему-то кажется, что хотя бы пара-тройка человек порадовалась тому, что найдено тривиальное решение не вполне тривиальной задачки.
Я, кстати, думал, что будет несколько сложнее.
Ну теперь следующий шаг - поженить этот код с бакгроундворкером и разнести Бешки по разным либам.
Разве не интересно - будет оно жить или где-то сломается?
назвать метод/переменную так
------
Есть у меня несколько сильно обфусканных сторонних дллок - там имена методов - _а4(), _а5()...
Да еще и полностью декомпилировать не получается - кусок связанный с идентификацией юсера и машины - сплошная ошибка декомпиляции.
Так что радуйся Процессу и Екзекуте...
-----
Интересней - может быть и нет, но всегда будет продуктивнее - Одна голова хорошо, а 1<<1 - лучше.
Неужели задачки не интересно порешать?
-----
Мне временами кажется, что нынешнему поколению действительно не интересно порешать задачки.
Т.е. работают они как чистые исполнители - объяснили что делать, объяснили как делать - работают.
Чуть только задача выпадает из области полученных разъяснений - тупик... сами - ни-ни... ждут пока
все пояснят... Может оно и правильно...
Мне временами кажется, что нынешнему поколению действительно не интересно порешать задачки.Т.е. работают они как чистые исполнители - объяснили что делать, объяснили как делать - работают.Чуть только задача выпадает из области полученных разъяснений - тупик... сами - ни-ни... ждут покавсе пояснят... Может оно и правильно...
Эй, ты, "вчерашнее поколение", если я тебе не тыкаю (в этот раз только сделаю исключение), то это не от возраста, а от воспитания. Чтобы мудрость из себя изображать, нужно для этого основания какие-то иметь, у Вас их нет.
Код то производит запись в поток, значит как раз то очень и относится.
-----
Код должен породить текст.
Вот тот текст, который порождается, меня интересует и интересует очень и очень сильно.
Именно то, какой текст будет порожден кодом и насколько сложно будет модифицировать
порождаемый код и составляет проблему.
То, как это будет реализовано технически - интересует только с позиции чтобы оно никак не
влияло на решение основной задачи.
Т.е. если мне для решения задачи не нужно знать об стреаме, не нужно его передавать или
еще как-то упоминать - это, несомненно, плюс.
Аналогично и по параметрам (тут не использовались) - если они НЕ болтаются под руками
- это тоже плюс.
Можно переписать немного по другому
-----
Можно. И даже - будет работать. Мало того - даже пару раз за последние полгода использовал
именно этот формат - нужно было обойти ошибку в подстановке значения с апострофами в
СКЛ. Но это было две строки на 1-1.5 мбайт шаблонов.
Вот два куска кода, делающие одно и то же:
VB
sql = "SELECT " & _
"TO_CHAR(fc.FC_BARCODE,'000000') ""bcd"", " & _
"fc.FC_BATCH_NO ""batchNo"", " & _
"fc.FC_SEQUENCE_NO ""seqNo"", " & _
"fc.FC_PANE_NO ""paneNo"", " & _
"fc.FC_GLAS_SEQ ""compNo"", " & _
"ps.PS_ORDER_NO ""orderNo"", " & _
"ps.PS_ORDER_POS ""itemNo"" " & _
"" & _
"FROM PRD_SEQ ps, PLAN_PARA pp, DAYBOOK db, FLOW_CTRL fc WHERE " & _
"" & _
"fc.FC_BATCH_NO=ps.PS_BATCH_NO AND " & _
"fc.FC_SEQUENCE_NO=ps.PS_SEQUENCE_NO AND " & _
"" & _
"ps.PS_ORDER_NO=db.DB_ORDER_NO AND " & _
"ps.PS_BATCH_NO BETWEEN db.DB_BATCH_NO_FROM AND db.DB_BATCH_NO_TO AND " & _
"" & _
"db.DB_MODE=pp.PP_NUMBER AND " & _
"DECODE(pp.PP_PURPOSE,3,1,4,1,0)=1 AND " & _
"" & _
"NOT EXISTS (" & _
"SELECT LBS_BCD " & _
"FROM C_LOG_BCD_STOCK WHERE " & _
"LBS_BCD=fc.FC_BARCODE AND " & _
"LBS_BATCH_NO=fc.FC_BATCH_NO AND " & _
"LBS_SEQUENCE_NO=fc.FC_SEQUENCE_NO" & _
") AND " & _
"" & _
"ps.PS_ORDER_NO=" & DRBcdStock.Item("orderNo").ToString & " AND " & _
"ps.PS_ORDER_POS=" & DRBcdStock.Item("itemNo").ToString & " AND " & _
"fc.FC_PANE_NO=" & DRBcdStock.Item("paneNo").ToString & " AND " & _
"fc.FC_GLAS_SEQ=" & DRBcdStock.Item("compNo").ToString & " " & _
"ORDER BY TO_CHAR(fc.FC_BARCODE,'000000')"
шаблон
<#@ template language="C#" inherits="Templates.Sql.TSqlTemplateBase" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
SELECT
TO_CHAR(fc.FC_BARCODE,'000000') "bcd",
fc.FC_BATCH_NO "batchNo",
fc.FC_SEQUENCE_NO "seqNo",
fc.FC_PANE_NO "paneNo",
fc.FC_GLAS_SEQ "compNo",
ps.PS_ORDER_NO "orderNo",
ps.PS_ORDER_POS "itemNo"
FROM PRD_SEQ ps,
PLAN_PARA pp,
DAYBOOK db,
FLOW_CTRL fc
WHERE fc.FC_BATCH_NO = ps.PS_BATCH_NO
AND fc.FC_SEQUENCE_NO = ps.PS_SEQUENCE_NO
AND ps.PS_ORDER_NO = db.DB_ORDER_NO
AND ps.PS_BATCH_NO BETWEEN db.DB_BATCH_NO_FROM AND db.DB_BATCH_NO_TO
AND db.DB_MODE = pp.PP_NUMBER
AND DECODE(pp.PP_PURPOSE,3,1,4,1,0) = 1
AND NOT EXISTS (
SELECT LBS_BCD
FROM C_LOG_BCD_STOCK
WHERE LBS_BCD = fc.FC_BARCODE
AND LBS_BATCH_NO = fc.FC_BATCH_NO
AND LBS_SEQUENCE_NO = fc.FC_SEQUENCE_NO
)
AND ps.PS_ORDER_NO = <#= OrderNo #>
AND ps.PS_ORDER_POS = <#= ItemNo #>
AND fc.FC_PANE_NO = <#= PaneNo #>
AND fc.FC_GLAS_SEQ = <#= CompNo #>
ORDER BY TO_CHAR(fc.FC_BARCODE,'000000')
Какой из них проще?
И нахрена во втором писать каждую строку через writer.StoreData(...)?
Тем более, что это сделает компилятор...
И если мне где-то надо вставить этот текст в другой, то
<#@ template language="C#" inherits="Templates.Sql.TSqlTemplateBase" #><#@ assembly name="System.Core" #><#@ import namespace="System.Linq" #><#@ import namespace="System.Text" #><#@ import namespace="System.Collections.Generic" #><#TAsql asql = new TASql();#>WITH A AS ( <#= asql.TransformText() #> )SELECT * FROM A
решает проблему и добавлять сюда какой-то стреам мне ну никак не хочется. Чем проще - тем лучше. Но работать - должно.
ВБшный код, если нужен, сам нарисуешь.
а каждая Бэшка реализует интерфейс IStoreData
-----
Можно. Нужно только поменять компилятор шаблонов. Или писать это дело руками для каждого класса...
Погонял в многопоточном режиме - все работает... На удивление - работает и работает нормально.
Видимо мелкомягкие сумели где-то спереть приличную реализацию потоков...
Вроде - уже постил, но что-то не вижу... видимо германка глючит...
using System;using System.IO;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace ThreadStaticTest3{interface IB{void GetResult();}class A : IB{[ThreadStatic]static StreamWriter sw = null;public StreamWriter Sw{get{if (sw == null){// get from class where instantiated/specified.throw new Exception("Output stream is null or not specified.");}return sw;}set { sw = value; }}public virtual void GetResult() { }}class B1 : A{String b1 = "B1";public override void GetResult(){Thread.Sleep(300);Sw.WriteLine(b1 + " 1");Thread.Sleep(300);IB b2 = Program.Factory.Create("B2"); // from different threadb2.GetResult();Thread.Sleep(300);Sw.WriteLine(b1 + " 2");Thread.Sleep(300);}}class B2 : A{String b2 = "B2";public override void GetResult(){Sw.WriteLine(b2);}}class Process{static int threads = 0;static object loker = new object();int thread;public Process(){lock (loker){++threads;thread = threads;}}public void Execute(){Thread newThread = new Thread(new ThreadStart(this.Generate));newThread.Name = threads.ToString();newThread.Start();}private void Generate(){using (StreamWriter sw = new StreamWriter("Data_" + thread.ToString() + ".dat")){B1 b1 = new B1();b1.Sw = sw;b1.GetResult();}}}class Factory{public IB Create(string pName){IB temp = null;switch(pName){case "B1":temp = new B1();break;case "B2":temp = new B2();break;default:throw new Exception("Factory can't create item - " + pName);}return temp;}}class Program{static void Main(string[] args){Thread.CurrentThread.Name = "Main";Factory = new Factory();for (int i = 0; i < 20; ++i){Process p = new Process();p.Execute();}}//private static Factory factory;//public static Factory Factory { get { return factory; } }public static Factory Factory { get; private set; }}}
Тут вроде все понятно.
Теперь об трудностях.
Есть такая радость - БэкгроундВоркер.
Пользовал Я его уже достаточно много, но пока не требовалось получать доступ к полям объекта после выполнения работы.
Кто-нибудь делал? Мне нужно вернуть стреам из Б1 в пулл по окончании работы.
А где здесь задачки?
К сожалению, я не знаю, что вам интересно и какой примерно тип мышления у вас. Поэтому подобрать стиль ответа непросто.
По моему мнению, задачки где то по "архитектуре ПО", вполне допускаю, что это вас абсолютно не интересует. А задачками будет типа "сделать прогу выводящую свой код".
Может Вы тогда приведёте пример задачи по Вашему?
но пока не требовалось получать доступ к полям объекта после выполнения работы.
Ничего не понял точно. Но если тебе нужно что то получить из завершившего свою работу потока, то кинь ему класс с началом работы, пусть пишет всё что тебе нужно. Оттуда и заберешь. Или еще можно копию данных через евент отослать.
Или еще можно копию данных через евент отослать.
-----
Угу...
Такой евент уже написан в БэкгроундВоркере.
Только вот у меня получить в нем копию данных не получается...
из завершившего свою работу потока
------
Будь, кстати, остопрожен - из завершившегося потока уже ничего получить нельзя...
Можно получить перед завершением. но 100% - синхронно.
Ну так и не привязывай это дело к первоначальной задаче.
стоп, стоп. У меня была информация только о задаче 1 и ёё я и пытался решать безо всякого контекста.
Теперь ты предлагаешь задачу 2..
Видмо тебе нужно решить задачу 3, но ты этого еще не можешь объяснить
стоп, стоп. У меня была информация только о задаче 1 и ёё я и пытался решать безо всякого контекста.
Теперь ты предлагаешь задачу 2..
-----
Возьми третью часть того поста - там где один из первых врапится - и реши ее через предлагаемый тобой вариант.
Потом сравни с тем что приведено в третьем блоке кода.
Где будет ПРОЩЕ?
Ну теперь представь, что ЭТО будет ваять... хммм... ну вон хоть Мышонок....
Может там еще упростить? До уровня <# GetResult("B2") #>? Меня ведь интересует только подстановка результата по месту написания с минимальными затратами.
Видмо тебе нужно решить задачу 3, но ты этого еще не можешь объяснить
-----
Таки - да, есть следующий фрагмент - уработать выше показанное в компактненькую и флексибилитную подсистемку генерации.
Ну там еще будет 3.а, 3.б, 4.а.б.ц.д.е... 556.а и т.п.
На то она и разработка...
Он живет до начала потока и после него.
-----
Если он не отдан потоку.
Я не уверен, что механизм сообщений удержит объект от освобождения. По крайней мере в обычных сообщения винды такой возможности нет.
Еще моментик, который, как мне кажется, ты упускаешь - используется пулл. Пулл не хранит ссылку на объект после его отдачи. Локальная переменная в методе - либо перезатрется, либо освободится с окончанием метода. Остается одна ссылка на объект - та, которая отдана потоку.
Проблема в том что она не доступна в комплитион-евенте.
Возьми третью часть того поста - там где один из первых врапится.. Потом сравни с тем что приведено в третьем блоке кода
Знаешь что это мне напоминает? "Пойди туду не знаю куда, возьми то не знаю что". То бишь ты то всё удерживаешь, а я не держу все нити в голове.
Ну там еще будет 3.а, 3.б, 4.а.б.ц.д.е... 556.а и т.п.На то она и разработка...![]()
ну не до такой же степени. Все главные требования должны быть известны ДО начала разработки, чтобы выработать правильный "концепт". Всё остальное может идти только в рамках модификации данного концепта. Ну или прийдется концепт менять, если новые хотелки настолько важны.
я не держу все нити в голове.
-----
Основная проблема в шаблонах - объем кода и сложность логики генерации.
Любое сокращение рассматриваемого объема кода или упрощение логики генерации - есть дело полезное и оправданное.
Потому код режется на более-менее понятные куски и пихается в разные шаблоны - до уровня понимабельности.
Когда все разобрано - надо собрать порожденный текст в кучку.
Так вот то что обсуждается - каким образом уменьшить затраты на собирание этого текста.
Затраты есть трудовые - количество времени на внесение изменений в существующие шаблоны.
И затраты есть технические - количество задействованных стреамов, памяти и общее время исполнения.
Когда ты, или кто еще, предлагаешь вариант имплементации Я больше всего думаю об том, насколько больше/меньше ручной работы потребуется в случае внесения изменений. Во вторую очередь - как оно отразится на ресурсах системы.
Вот тебе и было предложено оценить трудозатраты в предлагаемом тобою варианте. Т.е. вместо:
<#@ template language="C#" inherits="Templates.Sql.TSqlTemplateBase" #><#@ assembly name="System.Core" #><#@ import namespace="System.Linq" #><#@ import namespace="System.Text" #><#@ import namespace="System.Collections.Generic" #>WITH A AS ( <# GetResult("B2"); #> )
SELECT * FROM A
написать что-то вида:
<#@ template language="C#" inherits="Templates.Sql.TSqlTemplateBase" #><#@ assembly name="System.Core" #><#@ import namespace="System.Linq" #><#@ import namespace="System.Text" #><#@ import namespace="System.Collections.Generic" #><# writer.StoreData(typeof(B2)) // B2 tut, odnako, nedostupno - est' IB...#>WITH A AS ( <# string temp = b2.TransformText(); stream.Write(temp); #> ) <# // tut ne slozhno, no nado pojasnit' kuda budet pisat'sja... #>
SELECT * FROM A <#+ new StreamWriter stream { get { return base.SW; } } // :) #> // что будет на вyходе?
Ну да - глупостей Я там намеренно налепил немеряно... и мог бы добавить и еще...
Но это чисто для индикации того, что код шаблона нужен как можно более простым, с удалением всего что мешает понимать каким будет результат.
что код шаблона нужен как можно более простым
Что то смутно припоминаю где то должен был проект МуркаТ4, но там дело было в параметрах помнится.
Но и по генерации было море ограничений. И что то с шаблонами мне больше не хочется связываться. Я бы всё равно делал по другому.
Не забывай что в 1м примере был приведен чисто код без упоминания шаблонов.
но там дело было в параметрах помнится.
-----
Ну так параметры - это другая задача.
Она рассмотрена в достаточной мере, выработано какое-то решение и лежит ждет имплементации.
Именно по этому сегодняшняя схема вообще не упоминает параметры.
И что то с шаблонами мне больше не хочется связываться.
был приведен чисто код без упоминания шаблонов.
-----
Ты их просто не умеешь готовить.
Собственно, чтобы не смущать всех шаблонами Я их и упростил до объекта с методом.
Грубо, но достаточно точно.
Я бы всё равно делал по другому.
-----
Ну, допустим, ты сделаешь идеальный, по твоему мнению, вариант.
Ну, допустим, Я посмотрю на твой вариант, восхищусь им до невозможности.
Ну, допустим, еще человек 5-10-15 будут в восхищении...
Вопрос - каким чудом можно будет обучить хотя бы 100-200 тыс прогеров пользоваться именно твоим вариантом?
Ну а если не получится - зачем пыхтеть и делать сервис для их загрузки/исполнения?
Смысл в том, чтобы получить результат используя простые и стандартные средства - тогда можно найти пользователей и сотворить гешефт.
Вопрос - каким чудом можно будет обучить хотя бы 100-200 тыс прогеров пользоваться именно твоим вариантом?
А каким чудом ты это получишь для твоего варианта?
Конечно я буду делать под то насколько знаю твою систему, а это где то возле -273 °C
То бишь прийдется многое воображать как оно может быть.
А так, мне достачно чтобы системой могли пользоваться люди заплатившие за это деньги. И там счёт идет явно не на тысячи.
Чтобы было понятно у не чисто софтверные проекты. Народ покупает железяку, а она без софта так и останется железякой.
По моему мнению, задачки где то по "архитектуре ПО", вполне допускаю, что это вас абсолютно не интересует. А задачками будет типа "сделать прогу выводящую свой код".Может Вы тогда приведёте пример задачи по Вашему?
Так Вы решили, что треп в этом топике - это "задачки где-то по архитектуре ПО"? Т.е. Вы - архитектор? Почему тогда уж сразу не Наполеон...
что треп в этом топике
Я вообще то думал что Вы имеете в виду совсем другой топик. Муркины проблемы не так просто классифицировать. Но в любом случае это задачки, хотя их и нужно довести до нормальной постановки.
Почему тогда уж сразу не Наполеон
Давайте жить дружно
Муркины проблемы не так просто классифицировать. Но в любом случае это задачки, хотя их и нужно довести до нормальной постановки.
То-то я и вижу, Вы с ним до хрипоты спорите, не можете определиться: кража или ограбление : )
PS. Интересно, кем вы оба были до революции...
Интересно, кем вы оба были до революции...
Увы похвасть нечем. Ананасов и рябчиковъ не жралисъ, за бананами на деревья не лазили. Хотя вот мурка вроде негром была.
Вы с ним до хрипоты спорите
Это со стороны видимо так наблюдается.
Помню, у нашего начальника волосы дыбом вставали, когда он случайно забегал в комнату во время обсуждения с коллегой как будем реализовывать тут или иную часть.
Жаркие были споры, но именно после них и рождалось более лучшее решение.
NB: влез исключительно от удивления сравнению архитектора с наполеоном.
Так Вы решили, что треп в этом топике - это "задачки где-то по архитектуре ПО"?
Может таковым оказаться. Если в конце не выяснится что ТС хотел узнать совсем другое, а все что он писал это так, от скуки.
Т.е. Вы - архитектор? Почему тогда уж сразу не Наполеон...
А откуда такой пиетет перед Software-архитекторами? Обычная работа. Или вы Enterprise-архитектора имели в виду? Но они не занимаются архитектурой ПО...
Чтобы было немного ясно о чём спор (об архитектуре)
Начало было здесь
https://foren.germany.ru/showmessage.pl?Number=31946268&Bo...
"как и назвать использование DLL'ов "плигином".- Что отсылает совсем к другому топику (уже моему). Вот относительно него я и отвечал.
Ну а перехода на личности я стараюсь избегать, у каждого своя точка зрения и если она не совпадет с твоей собственной, то это не должно означать что другой "дурак".
Иногда можно просто иметь в виду совсем другое, а иногда представлять проблему в своем видении, ну и много чего другого.
Но там ясно написано: Мурр (он!)
А что это для вас это имеет какой то большой смысл в данном случае? Что на этом нужно заострять внимание или просто больше не к чему придраться?
В предложении было использовано имя Мурка, скажем так, по поэтическим соображениям Может еще и все слова нужно правильно писать?
Ничего, не расстраивайтесь. Это не страшно. Быдлячить отучитесь, словарный запас увеличите, хорошим специалистом станете и вас обязательно пригласят.
Но возвращаясь к моему вопросу: может скажете что вас так удивило в том, что в эту ветку может заглянуть архитектор?
Заглянуть, безусловно, может. Но пока этого не произошло.
Ну почему же. Я уже заглянул.
Быдло одно, как Вы сами себя обозначили (и Вы правы, наверное).
Передергиваете. Быдлом я называл только вас (или вы и процитированный мною анекдот не знаете?). А кроме вас в этой ветке и другие люди пишут.
Можете больше не тужиться, я на Вас больше не отреагирую.
Ничего страшного. Форум открытый, остальные почитают.
N.P.
Таки Я молодец и таки Я собрал работающую схему многопоточки...
Должен сказать, что работает шустро и даже аккуратно обрабатывает ошибки.
Быстро - эtо, что ранее на этом же хосте (И5-2320, 8Гб РАМ и ССД) в 1 поток делалось за 20-25 секунд, сейчас в 10 потоков делается за 0.9 секунды.
Меня - устраивает, но нужно посмотреть как скажется изменение количества потоков на работе системы.
Нужно еще разобраться с двумя моментами - те самые параметры (они уже есть, но не устраивает имплементация)
и управление выводом - тут надо иметь возможность дампить в сеть без записи на диск... или эмулировать диск в памяти...
По последнему есть вопросик - кто-нибудь видел имплементацию эмулятора диска, способного представлять файлами внешние по отношению к эмулятору, МемориСтреамы? Не хочется привязываться к файловой системе - нужно просто имя и возможность блочно читать МемориСтреам...