2016-07-06 4 views
2

Я работаю над проектом, и мне нужно нарисовать блоки изображений (в виде растровых изображений), которые я получаю из сокета на уже существующее изображение (которое я определяю в начале программы), и отобразить его на PictureBox - другими словами, обновлять изображение каждый раз, когда я получаю новый блок.C# Рисование растрового изображения над другим

Чтобы сделать это асинхронно, я использую Thread, который считывает данные с Socket и обрабатывает его.

Это мой код:

private void MainScreenThread() { 

ReadData(); 
initial = bufferToJpeg(); //full screen first shot. 
pictureBox1.Image = initial; 

while (true) { 
int pos = ReadData(); 
int x = BlockX(); 
int y = BlockY(); 
Bitmap block = bufferToJpeg(); //retrieveing the new block. 

Graphics g = Graphics.FromImage(initial); 
g.DrawImage(block, x, y); //drawing the new block over the inital image. 
this.Invoke(new Action(() => pictureBox1.Refresh())); //refreshing the picturebox-will update the intial; 

} 
} 
    private Bitmap bufferToJpeg() 
    { 
     return (Bitmap)Image.FromStream(ms);   
    } 

Я получаю сообщение об ошибке

объект используется в настоящее время в других местах

На линии Graphics создания

Graphics g = Graphics.FromImage(initial); 

Я не использую какие-либо другие темы или не имею доступа к растровому изображению. Так что я не уверен, в чем проблема здесь.

Если кто-нибудь может просветить меня, я буду очень благодарен.

Спасибо.

+0

Вы только что обнаружили, что ни PictureBox, ни класс Bitmap потокобезопасны. К счастью, в классе битмапа есть встроенная для этого диагностика, kaboom, когда вы используете Graphics.FromImage() в то же самое время, когда PictureBox реплицирует себя. Довольно случайные, как и ошибки с чередованием. Вам нужно вызвать больше кода, а также Graphics.FromImage и DrawImage. Или создайте свой собственный потокобезопасный класс PictureBox, его переопределению OnPaint() необходимо выполнить блокировку, которую вы также используете в этом методе. –

+0

Скорее всего, вы быстро столкнетесь с «OutOfMemoryException» с этим, вам нужно избавиться от «блока» в каждом цикле и избавиться от 'g', когда вы закончите. –

ответ

1

Попытка присвоить графику перед циклом:

private void MainScreenThread() { 

    ReadData(); 
    initial = bufferToJpeg(); 
    pictureBox1.Image = initial; 
    Graphics g = Graphics.FromImage(initial); 

    while (true) { 
    int pos = ReadData(); 
    int x = BlockX(); 
    int y = BlockY(); 
    Bitmap block = bufferToJpeg(); 

    g.DrawImage(block, x, y); 
    this.Invoke(new Action(() => pictureBox1.Refresh())); 

    } 
} 
-1

Потому что вы никогда не располагаете графическим объектом после его использования.

Если вы посмотрите на графический компонент, создайте его. Вы используете «начальное» растровое изображение. Графика теперь указывает на этот «первоначальный» объект, первый раз ему удастся создать графику, но второй раз (поскольку «g» не был удален/выпущен), «начальный» объект все еще используется старой графики перед созданием новой.

Что вы можете сделать, это:

private void MainScreenThread() { 

    ReadData(); 
    initial = bufferToJpeg(); //full screen first shot. 
    pictureBox1.Image = initial; 

    while (true) { 
    int pos = ReadData(); 
    int x = BlockX(); 
    int y = BlockY(); 
    Bitmap block = bufferToJpeg(); //retrieveing the new block. 

    using(Graphics g = Graphics.FromImage(initial)) { 
     g.DrawImage(block, x, y); //drawing the new block over the inital image. 
     this.Invoke(new Action(() => pictureBox1.Refresh())); //refreshing the picturebox-will update the intial; 
    } 
} 
} 

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

Редактировать: Fix- Не правильно включил весь код в виде кодового блока.

+0

Я также подумал об этом, поэтому раньше использовал 'Dispose', и теперь я использую' Using() 'statement ... к сожалению, я получаю точно такую ​​же ошибку .... в той же строке ...' object is в настоящее время используется в другом месте @Karl Patrik Johansson – Slashy

+0

Хм, значит, это должно быть потому, что он используется в окне изображения?Возможно, попробуйте клонировать исходное растровое изображение перед созданием графики и назначьте клонированное растровое изображение как новое изображение на кадре. ex: 'var img = (битмап) initial.Clone(); используя (Graphics g = Graphics.FromImage (img)) ', а затем' this.Invoke (новое действие (() => pictureBox1.Image = img)); ' –

+0

теперь я получаю ошибку при создании клона в этой строке 'var img = (Bitmap) initial.Clone();' @Karl Patrik Johansson – Slashy

Смежные вопросы