Информация об изменениях

Сообщение Re[5]: Как вызвать метод формы из родительского потока? от 18.09.2014 12:24

Изменено 18.09.2014 12:38 fortnum

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

D>Поток с формой запускается при активизации COM+ объекта и отображает иконку в трее.

D>При удалении COM+ объекта надо бы форму высвободить — по идее, это должно привести к закрытию потока (ибо Application.Run).
D>С чем, собственно, и был связан мой первоначальный вопрос.

А почему ты хочешь управлять формой из компонента? На мой взгляд — это не самое лучшее решение в плане архитектуры. Наверняка, ты еще из этой формы своим компонентом управляешь, или периодически мониторишь его состояние. Короче, у тебя, подозреваю, сейчас двунаправленная логическая связь "компонент"<->"форма". Гораздо лучше сделать так, чтобы либо компонент ничего не знал о форме, либо форма ничего не знала о компоненте. Т.к. в форме, не знающей ничего о компоненте, смысла нет, то получается, надо сделать так: "компонент"<-"форма". Т.е. компонент ничего не знает о форме, а форма знает о компоненте. Более того, форма для компонента, по сути, — тот же клиент. Поэтому я бы предложил решить вопрос ближе к такому варианту:

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    static class Program
    {
        static void Main()
        {
            Console.WriteLine("Клиент: нажми любую клавишу, чтобы подключиться к серверу."); Console.ReadKey(true);

            var threadUIClass1 = Task.Run(() => new ThreadUIClass1()).Result;

            Console.WriteLine("Клиент: нажми любую клавишу, чтобы отключиться от сервера."); Console.ReadKey(true);

            Task.Run(() => threadUIClass1.Dispose());

            Console.WriteLine("Press any key to exit.");
            Console.ReadKey(true);
        }

        public class ThreadUIClass1 : IDisposable
        {
            volatile int _data;

            volatile bool _disposed;

            public ThreadUIClass1()
            {
                new Thread(() =>
                {
                    while (!_disposed)
                    {
                        Task.Delay(100).Wait();

                        _data = new Random().Next(int.MinValue, int.MaxValue);
                    }

                    Console.WriteLine("Сервер: рабочий поток завершен."); 
                }).Start();

                Console.WriteLine("Сервер: рабочий поток запущен."); 

                new Thread(() => 
                {
                    var form = new Form();

                    var timer = new System.Windows.Forms.Timer() { Interval = 5000 };

                    timer.Tick += (o, e) =>
                    {
                        form.Text = _data.ToString();

                        if (_disposed)
                        {
                            form.Dispose();
                        }
                    };

                    timer.Start();

                    Console.WriteLine("Сервер: локальный пользовательский интерфейс запущен."); 

                    Application.Run(form);

                    Console.WriteLine("Сервер: локальный пользовательский интерфейс остановлен."); 
                }).Start();
            }

            public void Dispose()
            {
                _disposed = true;

                Console.WriteLine("Сервер: удаленный клиент отсоединен."); 
            }
        }
    }
}
Re[5]: Как вызвать метод формы из родительского потока?
Здравствуйте, mDmitriy, Вы писали:

D>Поток с формой запускается при активизации COM+ объекта и отображает иконку в трее.

D>При удалении COM+ объекта надо бы форму высвободить — по идее, это должно привести к закрытию потока (ибо Application.Run).
D>С чем, собственно, и был связан мой первоначальный вопрос.

А почему ты хочешь управлять формой из компонента? На мой взгляд — это не самое лучшее решение в плане архитектуры. Наверняка, ты еще из этой формы своим компонентом управляешь, или периодически мониторишь его состояние. Короче, у тебя, подозреваю, сейчас двунаправленная логическая связь "компонент"<->"форма". Гораздо лучше сделать так, чтобы либо компонент ничего не знал о форме, либо форма ничего не знала о компоненте. Т.к. в форме, не знающей ничего о компоненте, смысла нет, то получается, надо сделать так: "компонент"<-"форма". Т.е. компонент ничего не знает о форме, а форма знает о компоненте. Более того, форма для компонента, по сути, — тот же клиент. Поэтому я бы предложил решить вопрос ближе к такому варианту:

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    static class Program
    {
        static void Main()
        {
            Console.WriteLine("Клиент: нажми любую клавишу, чтобы подключиться к серверу."); Console.ReadKey(true);

            var threadUIClass1 = Task.Run(() => new ThreadUIClass1()).Result;

            Console.WriteLine("Клиент: нажми любую клавишу, чтобы отключиться от сервера."); Console.ReadKey(true);

            Task.Run(() => threadUIClass1.Dispose());

            Console.WriteLine("Press any key to exit.");
            Console.ReadKey(true);
        }

        public class ThreadUIClass1 : IDisposable
        {
            volatile int _data;

            volatile bool _disposed;

            public ThreadUIClass1()
            {
                new Thread(() =>
                {
                    while (!_disposed)
                    {
                        Task.Delay(100).Wait();

                        _data = new Random().Next(int.MinValue, int.MaxValue);
                    }

                    Console.WriteLine("Сервер: рабочий поток завершен."); 
                }).Start();

                Console.WriteLine("Сервер: рабочий поток запущен."); 

                new Thread(() => 
                {
                    var form = new Form();

                    form.Load += (o, e) =>
                    {
                        var timer = new System.Windows.Forms.Timer() { Interval = 5000 };

                        timer.Tick += (t, x) =>
                        {
                            form.Text = _data.ToString();

                            if (_disposed)
                            {
                                form.Dispose();
                            }
                        };

                        timer.Start();
                    };

                    Console.WriteLine("Сервер: локальный пользовательский интерфейс запущен."); 

                    Application.Run(form);

                    Console.WriteLine("Сервер: локальный пользовательский интерфейс остановлен."); 
                }).Start();
            }

            public void Dispose()
            {
                _disposed = true;

                Console.WriteLine("Сервер: удаленный клиент отсоединен."); 
            }
        }
    }
}