Как сделать перерисовку формы максимально быстрой
От: Streamer1 Украина  
Дата: 27.04.06 06:51
Оценка:
Есть приложение на C#, в котором создается поток рисующий битмапы,
необходимо максимально быстро проинформировать основной поток программы
что необходимо произвести перерисовку, при этом не задерживая исполнение
потока до завершения отрисовки. Если на момент обновления не завершена
предыдущая отрисовка, то отрисовку не делать.
Приложение почти рилтайм частота перерисовки формы >= 50 раз в секунду.
Требуется максимальная скорость. Как это можно сделать?

вызов Invalidate у формы приводит к остановке выполнения до окончания отрисовки...
семафоры и другие эвенты лучше не использовать — сильно тормозят выполнение программы...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Как сделать перерисовку формы максимально быстрой
От: Andrbig  
Дата: 27.04.06 07:30
Оценка:
Здравствуйте, Streamer1, Вы писали:

S>Есть приложение на C#, в котором создается поток рисующий битмапы,

Рабочий поток не должен заниматься рисованием, его задача — сгенерить данные.

S>Приложение почти рилтайм частота перерисовки формы >= 50 раз в секунду.

S>Требуется максимальная скорость. Как это можно сделать?

При таком раскладе не надо никому ничего сообщать. Заведи таймер, срабатывающий так часто, как тебе надо. Таймер возьмет последние данные от рабочего потока и их отрисует. Все, не надо никаких усложнений.
Re[2]: Как сделать перерисовку формы максимально быстрой
От: Streamer1 Украина  
Дата: 27.04.06 07:51
Оценка:
Здравствуйте, Andrbig, Вы писали:

A>При таком раскладе не надо никому ничего сообщать. Заведи таймер, срабатывающий так часто, как тебе надо. Таймер возьмет последние данные от рабочего потока и их отрисует. Все, не надо никаких усложнений.


ха

я так и делал вначале, поставил таймер на 20 мс и по нему делал Invalidate, но
по какимто причинам таймер срабатывает не раз в 20 мс, а как ему вздумается —
то раз в 3 секунды, то раз в секунду, короче обновление получается в среднем
раз в несколько секунд. В чем дело не знаю... поэтому стал делать Invalidate из
потока отрисовки, но это стало заметно тормозить поток отрисовки, а его тормозить нельзя
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Как сделать перерисовку формы максимально быстрой
От: Andrbig  
Дата: 27.04.06 08:06
Оценка:
Здравствуйте, Streamer1, Вы писали:

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


A>>При таком раскладе не надо никому ничего сообщать. Заведи таймер, срабатывающий так часто, как тебе надо. Таймер возьмет последние данные от рабочего потока и их отрисует. Все, не надо никаких усложнений.


S>ха


S>я так и делал вначале, поставил таймер на 20 мс и по нему делал Invalidate, но

S>по какимто причинам таймер срабатывает не раз в 20 мс, а как ему вздумается -
S>то раз в 3 секунды, то раз в секунду, короче обновление получается в среднем
S>раз в несколько секунд. В чем дело не знаю... поэтому стал делать Invalidate из
S>потока отрисовки, но это стало заметно тормозить поток отрисовки, а его тормозить нельзя

ха

Сравни то что ты делал с тем что я предложил. Ты каждые 20мс бросал invalidate, а отрисовка видимо шла дольше 20 мс — в результате очередь сообщений забивалась этими Invalidate-ми под завязку. А поскольку таймер — в той же очереди, то неудивительно, что он стал работать с перерывами. Ты сам его и затормозил.

Я же предлагаю делать Paint в таймере, а в OnPaint контрола ничего не делать — все равно таймер работает часто.

Хотя сам бы я делал по другому: я в конце OnPaint запускал бы серверный таймер на 20 мс, который бы бросил Invalidate.
Re[2]: Как сделать перерисовку формы максимально быстрой
От: Streamer1 Украина  
Дата: 27.04.06 08:18
Оценка: +1
Здравствуйте, Andrbig, Вы писали:

A> Рабочий поток не должен заниматься рисованием, его задача — сгенерить данные.


сорри за неточную формулировку поток занимается не "рисованием", а "генерацией" битмапов, которые должны быть отрисованы в окне, битмапы это данные которые он генерит
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Как сделать перерисовку формы максимально быстрой
От: Streamer1 Украина  
Дата: 27.04.06 08:41
Оценка:
Здравствуйте, Andrbig, Вы писали:

A>Сравни то что ты делал с тем что я предложил. Ты каждые 20мс бросал invalidate, а отрисовка видимо шла дольше 20 мс — в результате очередь сообщений забивалась этими Invalidate-ми под завязку. А поскольку таймер — в той же очереди, то неудивительно, что он стал работать с перерывами. Ты сам его и затормозил.


скорее всего так и есть

A>Я же предлагаю делать Paint в таймере, а в OnPaint контрола ничего не делать — все равно таймер работает часто.

A>Хотя сам бы я делал по другому: я в конце OnPaint запускал бы серверный таймер на 20 мс, который бы бросил Invalidate.

попробую последний вариант... спасибо
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Как сделать перерисовку формы максимально быстрой
От: Кремер Евгений Германия  
Дата: 27.04.06 16:27
Оценка:
Здравствуйте,

>При таком раскладе не надо никому ничего сообщать. Заведи таймер, срабатывающий так часто, как тебе надо. Таймер возьмет последние данные от рабочего потока и их отрисует. Все, не надо никаких усложнений.


Возможно это не вызывает никаких усложнений для программиста, а для процессора всё же.
Обязательная перерисовка формы, не зависимо от того обновились ли данные или нет, теряем драгоценные такты рабочего потока!
Я попробовал только что и не смог уловить синхронность invalidate();. Я перед вызовом этой функции установил breakpoint в onpaint(), вызвал её и никакого перехода в onpaint() не произошло, только после завершения текущей процедуры произошёл переход в onpaint(), что говорит об асинхронности. Я бы выбрал вариант с invalidate.
Если нет надобности в рисовании всех изображений, а только в их производстве, напрашивается вопрос "а зачем они тогда?".

А как Вы рисуете, А где (метод) рисуете, А что Вам вдействительности важно рисовать или производить?
Posted via RSDN NNTP Server 2.0
Re: Как сделать перерисовку формы максимально быстрой
От: WolfHound  
Дата: 27.04.06 18:32
Оценка: 2 (1)
Здравствуйте, Streamer1, Вы писали:

Ну както так:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;

namespace TMDraw
{
    public static class Program
    {
        public class Generator
        {
            object m_Lock = new object();
            List<Bitmap> m_Ready = new List<Bitmap>();
            List<Bitmap> m_Ret = new List<Bitmap>();
            Font m_Font = new Font(FontFamily.GenericMonospace, 15, FontStyle.Bold);

            public Generator()
            {
                for (int i = 0; i < 3; ++i)
                {
                    Bitmap bm = new Bitmap(100, 100);
                    Draw(bm);
                    m_Ready.Add(bm);
                }
            }

            public void Work()
            {
                while (true)
                {
                    Bitmap bm;
                    lock (m_Lock)
                    {
                        if (m_Ret.Count > 0)
                        {
                            bm = m_Ret[0];
                            m_Ret.RemoveAt(0);
                        }
                        else
                        {
                            bm = m_Ready[0];
                            m_Ready.RemoveAt(0);
                        }
                    }
                    Draw(bm);
                    lock (m_Lock)
                    {
                        m_Ready.Add(bm);
                    }
                }
            }

            public Bitmap GetBitmap()
            {
                lock (m_Lock)
                {
                    Bitmap bm;
                    if (m_Ready.Count > 0)
                    {
                        bm = m_Ready[m_Ready.Count - 1];
                        m_Ready.RemoveAt(m_Ready.Count - 1);
                    }
                    else
                    {
                        bm = m_Ret[m_Ret.Count - 1];
                        m_Ret.RemoveAt(m_Ret.Count - 1);
                    }
                    return bm;
                }
            }

            public void ReturnBitmap(Bitmap bm)
            {
                lock (m_Lock)
                {
                    m_Ret.Add(bm);
                }
            }

            int frames = 0;
            float f = 0;
            void Draw(Bitmap bm1)
            {
                frames++;
                f += 0.01f;
                if (f > 100)
                    f = 0;
                using (Graphics g = Graphics.FromImage(bm1))
                {
                    g.Clear(Color.Gold);
                    g.DrawLine(Pens.Red, 0, 0, f, f);
                    g.DrawString(frames.ToString(), m_Font, Brushes.Black, 0, 0);
                }
            }
        }

        static void Main()
        {
            Generator g = new Generator();
            Thread t = new Thread(g.Work);
            try
            {
                t.Start();

                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1(g));
            }
            finally
            {
                t.Abort();
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace TMDraw
{
    public partial class Form1 : Form
    {
        Program.Generator g;
        public Form1(Program.Generator g)
        {
            this.g = g;
            InitializeComponent();
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            //base.OnPaintBackground(e);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Bitmap bm = g.GetBitmap();
            e.Graphics.DrawImage(bm, 0, 0, Width, Height);
            g.ReturnBitmap(bm);
            Invalidate();
            Thread.Sleep(1);//Это важно иначе этот поток будет глушить генерирующий поток
        }
    }
}
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Как сделать перерисовку формы максимально быстрой
От: Аноним  
Дата: 27.04.06 22:39
Оценка:
Здравствуйте, Streamer1, Вы писали:

S>Приложение почти рилтайм частота перерисовки формы >= 50 раз в секунду.


А смысл ? Свыше 24 кадров всё одно человек не увидит Так что требование понижаем до 30 раз — уже легче.

Ну а если всё-таки надо свыше 50 fps — смотрим в сторону DirectX/OpenGL и не напрягаем бедный процессор
Re[2]: Как сделать перерисовку формы максимально быстрой
От: Streamer1 Украина  
Дата: 28.04.06 07:05
Оценка:
Здравствуйте, <Аноним>, Вы писали:

S>>Приложение почти рилтайм частота перерисовки формы >= 50 раз в секунду.


А>А смысл ? Свыше 24 кадров всё одно человек не увидит Так что требование понижаем до 30 раз — уже легче.


очень даже большой смысл, достаточно уменьшить частоту с 50 Гц до 49 и все, конец света бегущая строка уже будет дергатся, а ты говоришь "всё одно человек не увидит", еще как увидит!

А>Ну а если всё-таки надо свыше 50 fps — смотрим в сторону DirectX/OpenGL и не напрягаем бедный процессор


c Managed DirectX еще не разобрался, DirectDraw зачемто выкинули (деприцировали так сказать ), надо через Direct3D делать...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Как сделать перерисовку формы максимально быстрой
От: Streamer1 Украина  
Дата: 28.04.06 07:14
Оценка:
Здравствуйте, Кремер Евгений, Вы писали:

КЕ>Здравствуйте,


>>При таком раскладе не надо никому ничего сообщать. Заведи таймер, срабатывающий так часто, как тебе надо. Таймер возьмет последние данные от рабочего потока и их отрисует. Все, не надо никаких усложнений.


КЕ>Возможно это не вызывает никаких усложнений для программиста, а для процессора всё же.

КЕ>Обязательная перерисовка формы, не зависимо от того обновились ли данные или нет, теряем драгоценные такты рабочего потока!
КЕ>Я попробовал только что и не смог уловить синхронность invalidate();. Я перед вызовом этой функции установил breakpoint в onpaint(), вызвал её и никакого перехода в onpaint() не произошло, только после завершения текущей процедуры произошёл переход в onpaint(), что говорит об асинхронности. Я бы выбрал вариант с invalidate.

на счет асинхронности я бы так не говорил, может по брейкпоинту этого и не видно, но Invalidate реально управление возвращает только тогда когда отрисовка уже произойдет... что сильно замедляет генерирующий поток, т.к. вызов Invalidate вызывается в нем...


КЕ>Если нет надобности в рисовании всех изображений, а только в их производстве, напрашивается вопрос "а зачем они тогда?".


КЕ>А как Вы рисуете, А где (метод) рисуете, А что Вам вдействительности важно рисовать или производить?


надобность есть в рисовании всех изображений, но при растягивании окна на отрисовку всех изображений скорости не хватает, а генерирующий битмапы поток жестко привязан ко времени и его задержки приводят к дестабилизации скорости. Генерирующий поток кроме битмапов генерирует в рилтайме звук и синхронизация его скорости производится именно по звуку. В таком контексте задержка потока вызовет треск в динамиках и резкое замедление программы.
Поэтому в отрисовке, при нехватке производительности, можно пожертвовать одним кадром — на медленных машинах редкое выпадание одного кадра в глаза бросаться не будет.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Как сделать перерисовку формы максимально быстрой
От: Кремер Евгений Германия  
Дата: 28.04.06 08:21
Оценка:
>на счет асинхронности я бы так не говорил, может по брейкпоинту этого и не видно, но Invalidate реально управление возвращает только тогда когда отрисовка уже произойдет... что сильно замедляет генерирующий поток, т.к. вызов Invalidate вызывается в нем...

а как вы вызываете invalidate() из другого потока (invoke, begininvoke ...)? я правда ничего не нашел в справке сдк о необходимости синхронизировать этот вызов из другого потока, но увидел подтверждение его асинхронности, а для синхронного рисования там рекомендуется Update. Как конечно МС это реализовало спорить не берусь.

>надобность есть в рисовании всех изображений...


Тогда можно было бы попробовать PostMessage c WM_USER+n, а в обработчике проверять флаг был ли битмап уже прорисован, на случай если в очереди стояли сразу 2 сообщения и первое рисовало последний битмап, а не то для которого оно было отправлено. За асинхронность не отвечаю, но лишнее рисование избежать точно можно.
Posted via RSDN NNTP Server 2.0
Re[4]: Как сделать перерисовку формы максимально быстрой
От: Дмитрий Наумов  
Дата: 28.04.06 08:51
Оценка:
Здравствуйте, Andrbig, Вы писали:

A>Сравни то что ты делал с тем что я предложил. Ты каждые 20мс бросал invalidate, а отрисовка видимо шла дольше 20 мс — в результате очередь сообщений забивалась этими Invalidate-ми под завязку. А поскольку таймер — в той же очереди, то неудивительно, что он стал работать с перерывами. Ты сам его и затормозил.


A>Я же предлагаю делать Paint в таймере, а в OnPaint контрола ничего не делать — все равно таймер работает часто.


A>Хотя сам бы я делал по другому: я в конце OnPaint запускал бы серверный таймер на 20 мс, который бы бросил Invalidate.


Маленькое уточнение: очередь забивается WM_PAINT'ами, которые "появляются" в результате вызова Invalidate. В очереди, не помню точно то ли подряд, то ли вообще, два WM_PAINT'а "не живут", они "сокращаются"
Сообщение WM_TIMER "ставится" в очередь очень хитро и там есть некоторые условия, одно из которых, например, если в очереди есть WM_PAINT, то WM_TIMER "ставится" не будет, пока не обработается WM_PAINT. Из этого следует:
1. Генерить прямо или косвенно сообщения WM_PAINT из обработчика WM_TIMER рискованно.
2. Расчитывать на точность WM_TIMER наивно
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Как сделать перерисовку формы максимально быстрой
От: Streamer1 Украина  
Дата: 28.04.06 17:11
Оценка:
Здравствуйте, Кремер Евгений, Вы писали:

>>на счет асинхронности я бы так не говорил, может по брейкпоинту этого и не видно, но Invalidate реально управление возвращает только тогда когда отрисовка уже произойдет... что сильно замедляет генерирующий поток, т.к. вызов Invalidate вызывается в нем...


КЕ>а как вы вызываете invalidate() из другого потока (invoke, begininvoke ...)? я правда ничего не нашел в справке сдк о необходимости синхронизировать этот вызов из другого потока, но увидел подтверждение его асинхронности, а для синхронного рисования там рекомендуется Update. Как конечно МС это реализовало спорить не берусь.


вначале вызывался просто mainForm.Invalidate(), сейчас через BeginInvoke, но не помогло...
возможно конечно проблема гдето в другом месте, сейчас алгоритм точно не помню нужно глянуть...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Как сделать перерисовку формы максимально быстрой
От: Streamer1 Украина  
Дата: 28.04.06 18:32
Оценка:
Здравствуйте, Дмитрий Наумов, Вы писали:

ДН>Маленькое уточнение: очередь забивается WM_PAINT'ами, которые "появляются" в результате вызова Invalidate. В очереди, не помню точно то ли подряд, то ли вообще, два WM_PAINT'а "не живут", они "сокращаются"

ДН>Сообщение WM_TIMER "ставится" в очередь очень хитро и там есть некоторые условия, одно из которых, например, если в очереди есть WM_PAINT, то WM_TIMER "ставится" не будет, пока не обработается WM_PAINT. Из этого следует:
ДН>1. Генерить прямо или косвенно сообщения WM_PAINT из обработчика WM_TIMER рискованно.
ДН>2. Расчитывать на точность WM_TIMER наивно

Хм, похоже дело именно в связи WM_PAINT и WM_TIMER, а как же быть?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: Как сделать перерисовку формы максимально быстрой
От: WolfHound  
Дата: 28.04.06 20:53
Оценка:
Здравствуйте, Streamer1, Вы писали:

А чем тебе мое решение не нравится?
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[7]: Как сделать перерисовку формы максимально быстрой
От: Streamer1 Украина  
Дата: 28.04.06 23:20
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>А чем тебе мое решение не нравится?


спасибо

я еще просто не разбирался в чем там смысл...
в runtime и при беглом осмотре сырцов выглядит заманчиво, но еще не понял насколько подходит под мою задачу, у меня задача не столько в генерации битмапа , сколько в быстрой асинхронной отрисовке его, отрисовке инициируемой генерирующим потоком. Цель минимальное время на вызов функции которая запустит в основном потоке программы отрисовку.

сейчас делается так:

в паралельном потоке крутится куча всякой всячины с отрисовкой битмапа, есть метод который рисует доступный в данный момент для рисования битмап:

      public override void DrawScreen(Graphics g, Rectangle rect)
      {
         ScreensSemaphore.WaitOne();
         g.DrawImage(Screens[CurrentScreen ^ 1], rect);
         ScreensSemaphore.Release();
      }


текущий битмап меняется генерирующим потоком:

      private unsafe void DrawUpdate()                               // dynamic update screen
      {
         if (pBase != null)
         {
            ScreensSemaphore.WaitOne();
            Screens[CurrentScreen].UnlockBits(bd);
            CurrentScreen ^= 1;
            ScreensSemaphore.Release();
         }
         if (UpdateSCR != null)
            UpdateSCR();
         Rectangle rect = new Rectangle(0, 0, ScreenWidth, ScreenHeight);
         bd = Screens[CurrentScreen].LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
         pBase = (Int32*)bd.Scan0.ToPointer();
      }


в промежутках между вызовами DrawUpdate производится создание битмапа используя указатель pBase

вот собственно код делегата UpdateSCR, который находится в основной форме:

      private void UpdateSCR()
      {
         Interlocked.Increment(ref FrameCount);
         ProcessInvalidateForm pif = new ProcessInvalidateForm();
         InvalidatingAsyncDelegate id = new InvalidatingAsyncDelegate(pif.InvalidateForm);
         id.BeginInvoke(this, null, null);
      }
....
   public delegate void InvalidatingAsyncDelegate(Form form);
   public class ProcessInvalidateForm
   {
      public void InvalidateForm(Form form)
      {
         form.Invalidate();
      }
   }


пока просматривал код заметил что DrawScreen может заблокировать поток через семафор...
наверно с этим и связано торможение потока...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[8]: Как сделать перерисовку формы максимально быстрой
От: Streamer1 Украина  
Дата: 28.04.06 23:26
Оценка:
Здравствуйте, Streamer1, Вы писали:

саму прогу можно посмотреть скачав ZXMAK.NET с сайта http://zx.da.ru (раздел эмуляторы) в рефлекторе можно код порассматривать, а то если все сюда запостить то ругаться будут, там 380 кб кода...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[8]: Как сделать перерисовку формы максимально быстрой
От: WolfHound  
Дата: 29.04.06 08:53
Оценка:
Здравствуйте, Streamer1, Вы писали:

S>я еще просто не разбирался в чем там смысл...

Там все дело в том что заводим 3 битмапа в один генерируем новое изображение, из другого рисуем на экран, а третий для того чтобы потоки друг друга не ждали. Хранение битмапов организовано так что на экран выводят всегда самый новый битмап, а рисуют всегда в самый старый.
S>в runtime и при беглом осмотре сырцов выглядит заманчиво, но еще не понял насколько подходит под мою задачу, у меня задача не столько в генерации битмапа , сколько в быстрой асинхронной отрисовке его, отрисовке инициируемой генерирующим потоком. Цель минимальное время на вызов функции которая запустит в основном потоке программы отрисовку.
Если тебе нужно чтобы именно генерирующий поток инициировал отрисовку на экран то тогда так
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;

namespace TMDraw
{
    public static class Program
    {
        public class Generator
        {
            object m_Lock = new object();
            List<Bitmap> m_Ready = new List<Bitmap>();
            Font m_Font = new Font(FontFamily.GenericMonospace, 15, FontStyle.Bold);

            public delegate void StartUpdate();
            StartUpdate m_StartUpdate;

            public Generator()
            {
                for (int i = 0; i < 3; ++i)
                {
                    Bitmap bm = new Bitmap(100, 100);
                    Draw(bm);
                    m_Ready.Add(bm);
                }
            }

            public void Init(StartUpdate startUpdate)
            {
                m_StartUpdate = startUpdate;
            }

            public void Work()
            {
                while (true)
                {
                    Bitmap bm;
                    lock (m_Lock)
                    {
                        bm = m_Ready[0];
                        m_Ready.RemoveAt(0);
                    }
                    Draw(bm);
                    lock (m_Lock)
                    {
                        m_Ready.Add(bm);
                    }
                    m_StartUpdate();
                }
            }

            public Bitmap GetBitmap()
            {
                lock (m_Lock)
                {
                    Bitmap bm = m_Ready[m_Ready.Count - 1];
                    m_Ready.RemoveAt(m_Ready.Count - 1);
                    return bm;
                }
            }

            public void ReturnBitmap(Bitmap bm)
            {
                lock (m_Lock)
                {
                    m_Ready.Insert(0, bm);
                }
            }

            int frames = 0;
            float f = 0;
            void Draw(Bitmap bm1)
            {
                frames++;
                f += 0.01f;
                if (f > 100)
                    f = 0;
                using (Graphics g = Graphics.FromImage(bm1))
                {
                    g.Clear(Color.Gold);
                    g.DrawLine(Pens.Red, 0, 0, f, f);
                    g.DrawString(frames.ToString(), m_Font, Brushes.Black, 0, 0);
                }
            }
        }

        static void Main()
        {
            try
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                Generator g = new Generator();
                Form1 form = new Form1();
                g.Init(delegate()
                {
                    form.BeginInvoke((Generator.StartUpdate)delegate()
                    {
                        if (!form.IsDisposed)
                            form.Update(g);
                    });
                });
                Thread t = new Thread(g.Work);
                try
                {
                    t.Start();
                    Application.Run(form);
                }
                finally
                {
                    t.Abort();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace TMDraw
{
    public partial class Form1 : Form
    {
        Program.Generator m_Generator = null;
        public Form1()
        {
            InitializeComponent();
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            if (m_Generator != null)
            {
                Bitmap bm = m_Generator.GetBitmap();
                e.Graphics.DrawImage(bm, ClientRectangle);
                m_Generator.ReturnBitmap(bm);
                m_Generator = null;
            }
        }

        internal void Update(Program.Generator g)
        {
            if (m_Generator == null)
            {
                m_Generator = g;
                Invalidate();
            }
        }
    }
}
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[9]: Как сделать перерисовку формы максимально быстрой
От: FR  
Дата: 29.04.06 16:51
Оценка:
Здравствуйте, Streamer1, Вы писали:

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


S>саму прогу можно посмотреть скачав ZXMAK.NET с сайта http://zx.da.ru (раздел эмуляторы) в рефлекторе можно код порассматривать, а то если все сюда запостить то ругаться будут, там 380 кб кода...


А тебе зачем все делать именно в отдельном потоке?
Эмулятор как я понимаю вещь близкая к играм, может лучше и сделать как в большинстве игр, все расчеты в основном цикле, и без остановки на ожидание сообщений. Как это сделать для C# можно посмотреть например тут http://rsdn.ru/forum/Message.aspx?mid=1837856&amp;only=1
Автор: mukhomor
Дата: 07.04.06
(второй способ)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.