Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Разработка Windows Forms > UserControl и многопоточность


Автор: 3she1on 17.12.2008, 19:17
Здравствуйте! Пишу сейчас свой контрол Ticker (бегущая строка) под dotNet CF. Есть небольшой вопрос. Вот приблизительный код контрола (не законченная версия):

Код

public partial class Ticker : UserControl
    {
        String textToView = String.Empty;
        int delay = 200;


        public UserControl1()
        {
            InitializeComponent();
        }

        public String TextToView
        {
            set { textToView = value;  }
            get { return textToView; }
        }

        public int Delay
        {
            set { delay = value; }
            get { return delay; }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            int x, y;
            x = 0;
            y = 2;
            Graphics g = e.Graphics;
            if (!textToView.Equals(String.Empty))
            {
                for (int i = 0; i < 20; i++)
                {
                    g.Clear(this.BackColor);
                    g.DrawString(textToView, this.Font, new SolidBrush(this.ForeColor), x, y);
                    x++;
                    Thread.Sleep(delay);
                }
            }
        }
    }


Когда юзаю контрол в приложениях происходит следующее: сам тикер рисует себя корректно, но при этом блокируется контейнер (форма, на которой лежит тикер). Когда внутри OnPaint класса Ticker цикл отрисовки проходит все итерации - управление нормально передается контейнеру (форме).

Контрол лепил вот так:

Код

public partial class Form1 : Form
    {
        delegate void initTicker();
        Ticker ticker;
        public Form1()
        {
            InitializeComponent();
            Thread t = new Thread(new ThreadStart(initializeTick));
            t.Start();
            t.Join();
        }

        private void initializeTick()
        {
            initTicker tickDelegate = new initTicker(addTick);
            this.Invoke(tickDelegate);
        }


        private void addTick()
        {
            ticker = new Titcker();
            ticker.TextToView = "this is ticker text";
            this.Controls.Add(ticker);
        }
        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("bla bla bla!");
        }
    }


Хотелось бы узнать как заставить их рисовать себя асинхронно. Заранее благодарен

Автор: Partizan 17.12.2008, 20:09
3she1on

надо саму процедуру отрисовки тикера в отдельный поток вынести...

То есть вот этот код - неплохо бы вынести в отдельный поток...
Код

           int x, y;
            x = 0;
            y = 2;
            Graphics g = e.Graphics;
            if (!textToView.Equals(String.Empty))
            {
                for (int i = 0; i < 20; i++)
                {
                    g.Clear(this.BackColor);
                    g.DrawString(textToView, this.Font, new SolidBrush(this.ForeColor), x, y);
                    x++;
                    Thread.Sleep(delay);
                }
            }

Автор: amarenkov 18.12.2008, 10:19
, а, поскольку, после этого получишь несколько ошибок, рисование во втором потоке надо производить на какой-нибудь Bitmap, созданный в том же потоке. А вот отрисовку на форму (т.е. в главный поток) придется синхронизировать и просто уже отрисованный Bitmap копировать на e.Graphics.

Автор: masterik 29.12.2008, 23:28
  •  Попробуй высчитывать координаты в отдельном потоке и вызывать оттуда обновление формы/контрола (Control.Invalidate), а в обработчике OnPaint только/уже рисовать на нужные/готовые координаты. Здесь также идеально подходит класс System.Windows.Forms.Timer.

    И как заметил amarenkov, чтобы избежать ошибок возможно придется воспользоваться парой Control.InvokeRequired и Control.Invoke.

  •  Не совсем понял логику "лепки" твоего контрола на форму.......
    Зачем делать это в отдельном потоке, когда ты все равно дожидаешься завершения работы потока (Thread.Join)?


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)