C # изображения, ошибка использования объекта в другом месте - PullRequest
2 голосов
/ 22 февраля 2011

Я чрезвычайно новичок в C #, так что извините, если я не объясню это хорошо.

Я извлекаю изображения с камеры своего компьютера и, наряду с отображением их в PictureBox, кодирую их в формате JPEG и отправляю их в общий словарь. вот мой код:

void CurrentCamera_OnImageCaptured(object sender, CameraEventArgs e)
        {
            this.pictureBoxMe.Image = e.Image;

            if (myName != "" && Form1.PicSent)
            {
                SendPic sendP = new SendPic((Image)e.Image.Clone());
                new System.Threading.Thread(new System.Threading.ThreadStart(sendP.send)).Start();
            }

        }

 public class SendPic
        {
            Image im;
            public SendPic (Image im)
            {
                this.im = im;
            }
            public void send(){

                Form1.PicSent = false;
                var memoryStream = new MemoryStream();

                im.Save(memoryStream, ImageFormat.Jpeg);

                var byteArray = memoryStream.ToArray();

                Form1.sd["/" + myName + "/video"] = byteArray;

                memoryStream.Close();
                Form1.PicSent = true;

            }
        }

проблема в том, что я получаю "Объект в настоящее время используется в другом месте". ошибка в строке: SendPic sendP = новый SendPic ((изображение) e.Image.Clone ());

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

Я читал что-то о блокировке? Как я могу реализовать это в этом случае? или есть что-то еще, что мне нужно сделать?

спасибо.

Ответы [ 2 ]

3 голосов
/ 22 февраля 2011

Он ведет себя так, как будто метод OnImageCaptured выполняется в потоке. Что не исключено для интерфейсов камеры. Установите точку останова и используйте окно Debug + Windows + Threads отладчика, чтобы увидеть, какой поток выполняет этот код.

Режим сбоя заключается в том, что поток пользовательского интерфейса обращается к изображению для рисования графического блока, одновременно с этим рабочий поток вызывает Clone (). GDI + не разрешает двум потокам одновременно обращаться к одному и тому же объекту изображения. Это действительно было бы странно, не сообщая, в какой именно момент времени поток пользовательского интерфейса начинает рисовать. PicSent - еще одна авария, ожидающая своего появления.

1 голос
/ 22 февраля 2011

Одна вещь, которая бросается в глаза, это то, что класс SendPic обращается к вашему словарю асинхронно (строка: Form1.sd["/" + myName + "/video"] = byteArray;).

Однако словари и хеш-таблицы не гарантированно поточно-ориентированы для операций записи.Вы должны быть в безопасности, если делаете код доступа к словарю потокобезопасным.Простой lock был бы способ начать.

Вроде как это:

public class SendPic
{
    private object lockobj = new object();
    // .... whatever other code ...

    public void send()
    {
       // .... whatever previous code ...

       lock(lockobj)
       {
          // assuming that the sd dictionary already has the relevant key
          // otherwise you'd need to do a Form1.sd.Add(key, byteArray)
          Form1.sd["/" + myName + "/video"] = byteArray;
       }

       // .... whatever following code ...
    }
} 

Цитата из MSDN:

Безопасность потоков Словарь <(Of <(TKey, TValue>)>) может поддерживать несколько читателей одновременно, если коллекция не изменена.Тем не менее, перечисление в коллекции по сути не является потокобезопасной процедурой. В редком случае, когда перечисление конкурирует с доступом для записи, коллекция должна быть заблокирована в течение всего перечисления. Чтобы разрешить доступ к коллекции из нескольких потоков для чтения и записи, вынеобходимо реализовать собственную синхронизацию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...