Re[10]: Как вызвать метод формы из родительского потока?
От: mDmitriy Россия  
Дата: 19.09.14 04:20
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Здравствуйте, mDmitriy, Вы писали:


F>>>И я не совсем понял, зачем был написан класс ThreadUIClass1 Есть компонент, форма, разделяемый компонентом и формой объект данных от компонента. А ThreadUIClass1 какую роль играет?

D>>ThreadUIClass1 — это оболочка над формой.
D>>Чтобы не загромождать код самого компонента.

F>То есть компонент создает экземпляр ThreadUIClass1, экземпляр ThreadUIClass1 создаёт форму? Если класс существует только и исключительно "для не загромождения кода", лучше использовать partial

Ну, код еще в процессе создания и будет еще рефакторится не раз.
Сейчас ThreadUIClass1 лежит вообще в отдельной dll вместе с формой.
Re: Как вызвать метод формы из родительского потока?
От: Clerk  
Дата: 19.09.14 07:07
Оценка:
Здравствуйте, mDmitriy, Вы писали:

  public class FormManager : IDisposable
  {
    Form    _form;
    Thread  _thread;

    public FormManager()
    {
      _form = new Form();
      _thread = new Thread(
        () => 
        {
          using (_form)
          {
            _form.ShowDialog();
          }
        });

      _thread.Start();
    }

    bool _disposed = false;

    public void Close()
    {
      if (!_disposed)
      {
        _disposed = true;

        // be sure that handle is there
        while (!_form.IsHandleCreated)
          Thread.Sleep(10);

        _form.Invoke((Action)(() => _form.Close()));

        while (_thread.ThreadState != ThreadState.Stopped)
          Thread.Sleep(1);
      }
    }

    public void Dispose()
    {
      Close();
    }
  }
Re[6]: Как вызвать метод формы из родительского потока?
От: Danchik Украина  
Дата: 19.09.14 12:24
Оценка:
Здравствуйте, 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]: Как вызвать метод формы из родительского потока?
От: drol  
Дата: 19.09.14 12:34
Оценка:
Здравствуйте, Danchik, Вы писали:

D> private volatile Form _form;


В такой реализации — на lock'ах — volatile не нужен.
Re[7]: Как вызвать метод формы из родительского потока?
От: mDmitriy Россия  
Дата: 19.09.14 12:42
Оценка: -1
Здравствуйте, Danchik, Вы писали:

D>[Skip]

D>Зачем так наворачивать... Два потока, да и слипы ганять.
D>Я с барьерами памяти, не игрался, вот попроще, на скорую руку
lock мне таки не нравится — это же не интенсивное многопоточное взаимодействие.
Re[8]: Как вызвать метод формы из родительского потока?
От: Danchik Украина  
Дата: 19.09.14 12:49
Оценка: +1
Здравствуйте, mDmitriy, Вы писали:

D>Здравствуйте, Danchik, Вы писали:


D>>[Skip]

D>>Зачем так наворачивать... Два потока, да и слипы ганять.
D>>Я с барьерами памяти, не игрался, вот попроще, на скорую руку
D>lock мне таки не нравится — это же не интенсивное многопоточное взаимодействие.

Тоесть крутить циклы со слипами это гут, а ДВА раза вызвать лок, это плохо? Где логика?
Re[8]: Как вызвать метод формы из родительского потока?
От: drol  
Дата: 19.09.14 12:59
Оценка:
Здравствуйте, mDmitriy, Вы писали:

D>lock мне таки не нравится — это же не интенсивное многопоточное взаимодействие.


Наоборот. Как раз потому что в задаче разовая операция именно lock для неё само то.
Re[7]: Как вызвать метод формы из родительского потока?
От: Fortnum  
Дата: 19.09.14 16:12
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Зачем так наворачивать... Два потока, да и слипы ганять.


Там помимо Main() три потока Моделирование рабочего потока, который _data обновляет. Других "слипов" в коде нигде нет — где ты их увидел, интересно . Еще UI-поток формы, и поток клиента COM-компонента (Task.Run в Main, через ThreadPool то бишь).

D>Я с барьерами памяти, не игрался, вот попроще, на скорую руку


Есть несколько на скорую руку вопросов по твоему коду. Вот некоторые из них.

Первый Вариант с двумя и более клиентскими потоками одного COM-компонента (одного экземпляра ThreadUIClass1) ты не рассматривал или просто не доделал? Я просто смотрю, как минимум _thread не защищена от этого.

Второй Зачем вообще диспоузить форму после выхода из Application.Run, если ей на тот момент уже был вызван Close, что подразумевает Dispose?

D>            var form = new Form();
D>            try
D>            {
D>                lock (_syncObj)
D>                {
D>                    _form = form;
D>                }
D>                Application.Run(form);
D>            }
D>            finally
D>            {
D>                lock (_syncObj)
D>                {
D>                    using (_form)
D>                        _form = null;
D>                }
D>            }


Третий Возможна такая ситуация, что вызов клиенту из RunThread уже вернется, и он тут же вызовет ThreadUIClass1.Dispose. Если это произойдет до присвоения значения _form = form, а произойти это может, т.к. Form.Show подразумевает вызов Form.Load, куда обычно навешивается много чего, тогда вызов TerminateThread проследует напрямую к _thread.Join(Int32.MaxValue), и форма останется висеть навечно.

Четвертый Зачем аргумент Int32.MaxValue в _thread.Join? Ты на самом деле надеешься, что кто-то или что-то будет ждать 24.855 суток?

Пятый Какую задачу выполняет вот этот Sleep?

D>        private void TerminateThread()
D>        {
D>            if (_thread != null)
D>            {
D>                Thread.Sleep(1000);


Есть еще вопросы, но они зависят от твоих ответов, так что пока всё
Re[9]: Как вызвать метод формы из родительского потока?
От: Fortnum  
Дата: 19.09.14 16:16
Оценка:
Здравствуйте, Danchik, Вы писали:

D>>>[Skip]

D>>>Зачем так наворачивать... Два потока, да и слипы ганять.
D>>>Я с барьерами памяти, не игрался, вот попроще, на скорую руку
D>>lock мне таки не нравится — это же не интенсивное многопоточное взаимодействие.
D>Тоесть крутить циклы со слипами это гут, а ДВА раза вызвать лок, это плохо? Где логика?

Во-во, я тебя и спрашиваю здесь
Автор: Fortnum
Дата: 19.09.14
, где ты там "слипы"-то увидал?
Re[9]: Как вызвать метод формы из родительского потока?
От: Fortnum  
Дата: 19.09.14 16:27
Оценка:
Здравствуйте, Danchik, Вы писали:

D>>>[Skip]

D>>>Зачем так наворачивать... Два потока, да и слипы ганять.
D>>>Я с барьерами памяти, не игрался, вот попроще, на скорую руку
D>>lock мне таки не нравится — это же не интенсивное многопоточное взаимодействие.
D>Тоесть крутить циклы со слипами это гут, а ДВА раза вызвать лок, это плохо? Где логика?

Логику, кстати, я пояснял: превратить двунаправленную логическую связь "компонент"<->"форма" в однонаправленную "компонент"<-"форма". Иначе, по сути, ты (а) запихиваешь контроллер формы в другой поток, (б) жестко увязываешь какой-то AppServer-компонент с UI — и то и другое неправильно. Если это не AppServer-компонент, а компонент, специально предназначенный для управления этой формы, тогда вообще не надо никаких потоков — для этого существует STA. На всякий случай и тут еще раз напишу — "слипов" нету.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.