Здравствуйте, Fortnum, Вы писали:
F>Здравствуйте, mDmitriy, Вы писали:
F>>>И я не совсем понял, зачем был написан класс ThreadUIClass1 Есть компонент, форма, разделяемый компонентом и формой объект данных от компонента. А ThreadUIClass1 какую роль играет? D>>ThreadUIClass1 — это оболочка над формой. D>>Чтобы не загромождать код самого компонента.
F>То есть компонент создает экземпляр ThreadUIClass1, экземпляр ThreadUIClass1 создаёт форму? Если класс существует только и исключительно "для не загромождения кода", лучше использовать partial
Ну, код еще в процессе создания и будет еще рефакторится не раз.
Сейчас ThreadUIClass1 лежит вообще в отдельной dll вместе с формой.
Re: Как вызвать метод формы из родительского потока?
Здравствуйте, Fortnum, Вы писали:
F>Здравствуйте, mDmitriy, Вы писали:
D>>Поток с формой запускается при активизации COM+ объекта и отображает иконку в трее. D>>При удалении COM+ объекта надо бы форму высвободить — по идее, это должно привести к закрытию потока (ибо Application.Run). D>>С чем, собственно, и был связан мой первоначальный вопрос.
F>А почему ты хочешь управлять формой из компонента? На мой взгляд — это не самое лучшее решение в плане архитектуры. Наверняка, ты еще из этой формы своим компонентом управляешь, или периодически мониторишь его состояние. Короче, у тебя, подозреваю, сейчас двунаправленная логическая связь "компонент"<->"форма". Гораздо лучше сделать так, чтобы либо компонент ничего не знал о форме, либо форма ничего не знала о компоненте. Т.к. в форме, не знающей ничего о компоненте, смысла нет, то получается, надо сделать так: "компонент"<-"форма". Т.е. компонент ничего не знает о форме, а форма знает о компоненте. Более того, форма для компонента, по сути, — тот же клиент. Поэтому я бы предложил решить вопрос ближе к такому варианту:
[Skip]
Зачем так наворачивать... Два потока, да и слипы ганять.
Я с барьерами памяти, не игрался, вот попроще, на скорую руку
public class ThreadUIClass1 : IDisposable
{
private volatile Form _form;
private Thread _thread;
private object _syncObj = new object();
public void Dispose()
{
TerminateThread();
}
private void TerminateThread()
{
if (_thread != null)
{
Thread.Sleep(1000);
Form form;
lock (_syncObj)
{
form = _form;
}
if (form != null && form.IsHandleCreated)
form.Invoke((MethodInvoker) (() => form.Close()));
_thread.Join(Int32.MaxValue);
_thread = null;
}
}
public void RunThread()
{
_thread = new Thread(RunApp);
_thread.Start();
}
private void RunApp(object obj)
{
var form = new Form();
try
{
form.Show();
lock (_syncObj)
{
_form = form;
}
Application.Run(form);
}
finally
{
lock (_syncObj)
{
using (_form)
_form = null;
}
}
}
}
Re[7]: Как вызвать метод формы из родительского потока?
Здравствуйте, Danchik, Вы писали:
D>[Skip] D>Зачем так наворачивать... Два потока, да и слипы ганять. D>Я с барьерами памяти, не игрался, вот попроще, на скорую руку
lock мне таки не нравится — это же не интенсивное многопоточное взаимодействие.
Re[8]: Как вызвать метод формы из родительского потока?
Здравствуйте, mDmitriy, Вы писали:
D>Здравствуйте, Danchik, Вы писали:
D>>[Skip] D>>Зачем так наворачивать... Два потока, да и слипы ганять. D>>Я с барьерами памяти, не игрался, вот попроще, на скорую руку D>lock мне таки не нравится — это же не интенсивное многопоточное взаимодействие.
Тоесть крутить циклы со слипами это гут, а ДВА раза вызвать лок, это плохо? Где логика?
Re[8]: Как вызвать метод формы из родительского потока?
Здравствуйте, Danchik, Вы писали:
D>Зачем так наворачивать... Два потока, да и слипы ганять.
Там помимо Main() три потока Моделирование рабочего потока, который _data обновляет. Других "слипов" в коде нигде нет — где ты их увидел, интересно . Еще UI-поток формы, и поток клиента COM-компонента (Task.Run в Main, через ThreadPool то бишь).
D>Я с барьерами памяти, не игрался, вот попроще, на скорую руку
Есть несколько на скорую руку вопросов по твоему коду. Вот некоторые из них.
Первый Вариант с двумя и более клиентскими потоками одного COM-компонента (одного экземпляра ThreadUIClass1) ты не рассматривал или просто не доделал? Я просто смотрю, как минимум _thread не защищена от этого.
Второй Зачем вообще диспоузить форму после выхода из Application.Run, если ей на тот момент уже был вызван Close, что подразумевает Dispose?
Третий Возможна такая ситуация, что вызов клиенту из RunThread уже вернется, и он тут же вызовет ThreadUIClass1.Dispose. Если это произойдет до присвоения значения _form = form, а произойти это может, т.к. Form.Show подразумевает вызов Form.Load, куда обычно навешивается много чего, тогда вызов TerminateThread проследует напрямую к _thread.Join(Int32.MaxValue), и форма останется висеть навечно.
Четвертый Зачем аргумент Int32.MaxValue в _thread.Join? Ты на самом деле надеешься, что кто-то или что-то будет ждать 24.855 суток?
Здравствуйте, Danchik, Вы писали:
D>>>[Skip] D>>>Зачем так наворачивать... Два потока, да и слипы ганять. D>>>Я с барьерами памяти, не игрался, вот попроще, на скорую руку D>>lock мне таки не нравится — это же не интенсивное многопоточное взаимодействие. D>Тоесть крутить циклы со слипами это гут, а ДВА раза вызвать лок, это плохо? Где логика?
Здравствуйте, Danchik, Вы писали:
D>>>[Skip] D>>>Зачем так наворачивать... Два потока, да и слипы ганять. D>>>Я с барьерами памяти, не игрался, вот попроще, на скорую руку D>>lock мне таки не нравится — это же не интенсивное многопоточное взаимодействие. D>Тоесть крутить циклы со слипами это гут, а ДВА раза вызвать лок, это плохо? Где логика?
Логику, кстати, я пояснял: превратить двунаправленную логическую связь "компонент"<->"форма" в однонаправленную "компонент"<-"форма". Иначе, по сути, ты (а) запихиваешь контроллер формы в другой поток, (б) жестко увязываешь какой-то AppServer-компонент с UI — и то и другое неправильно. Если это не AppServer-компонент, а компонент, специально предназначенный для управления этой формы, тогда вообще не надо никаких потоков — для этого существует STA. На всякий случай и тут еще раз напишу — "слипов" нету.