C++ Cli передает указатели изображений в WPF для отображения

Моя обработка изображений полностью выполнена на C++. Использовал MFC, сейчас изучаю возможность обновления до WPF. Сторона WPF будет в основном пользовательским интерфейсом, я передаю указатели изображений из неуправляемого в управляемое для отображения. Я обнаружил, что если я использую поток для зацикливания вектора бэкэнда, он ничего не отобразит, но если я изменю его на триггер кнопки один за другим, он будет работать. С теми же функциями понятия не имею, что происходит.

WPF владеет моим объектом CppCli, который может напрямую вызывать любую функцию в c++/cli. Что здесь может быть не так.

код wpf cs:

private CppCli cli;

public MainWindow() { 
    cli = new CppCli(); 
    cli.ImageUpdated += Cli_ImageUpdated; // delegate and event to call method Cli_ImageUpdated 
    InitializeComponent(); 
}

private void Cli_ImageUpdated(object sender, ImageUpdateEventArgs e) 
{ 
    Dispatcher.Invoke(() =>
    {
        MyImageControl.Source = e.img;
    });
} 

private void LiveToggle_Click(object sender, RoutedEventArgs e) {

    cli.LiveToggle(); 
}

CPP-код CLI:

public ref class ImageUpdateEventArgs : EventArgs { 
    public: BitmapSource^ img;

    ImageUpdateEventArgs(BitmapSource^ bitmap) { 
        img = bitmap;
    } 
};

void CppCli::LiveToggle() { 
    running = !running; 

    if (running) { 
        liveThread = gcnew Thread(gcnew ThreadStart(this, &MathFunctions::UpdateDisplay)); 
        liveThread->IsBackground = true; 
        liveThread->Start();
    }

    //UpdateDisplay() // This works if replace the whole thing above. 
}

void CppCli::UpdateDisplay() { 
    while (running) { // Remove this while loop and it works.

        int stride, rows, cols, bufferSize; 
        stride = cvObj->images[imageIndex].step[0]; 
        rows = cvObj->images[imageIndex].rows; 
        cols = cvObj->images[imageIndex].cols; 
        bufferSize = cvObj->images[imageIndex].total() * cvObj->images[imageIndex].elemSize(); 
        IntPtr ptr(cvObj->images[imageIndex].ptr()); 

        ImageUpdated(this, gcnew ImageUpdateEventArgs(BitmapSource::Create(cols, rows, 96, 96, PixelFormats::Bgra32, nullptr, ptr, bufferSize, stride)));

        Thread::Sleep(100); 
        imageIndex++; 
        if (imageIndex >= cvObj->images.size())
        { 
            imageIndex = 0;
        }
    } 
}

Возможно, вы захотите использовать WritaableBitmap вместо создания новых BitmapSources при каждом вызове ImageUpdated. BackBuffer объекта WritableBitmap можно заблокировать, чтобы он был доступен из потока, отличного от потока пользовательского интерфейса.

Clemens 15.07.2024 08:39

Плохо, я не знал о формате stackoverflow, пока он не стал доступен для чтения. Я также тестирую WriteableBitmap. Есть ли способ указать с его помощью разные указатели? Это означает, что я просто меняю указатели на буферы изображений.

Sean Tan 15.07.2024 09:00

Вы должны скопировать в BackBuffer.

Clemens 15.07.2024 09:22

liveThread — это новый поток для вызова UpdateDisplay(). Это не основная тема, верно?

Sean Tan 15.07.2024 09:39
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку BitmapSource создается в потоке, отличном от потока пользовательского интерфейса, его необходимо заморозить перед присвоением свойству Source элемента Image в потоке пользовательского интерфейса:

private void Cli_ImageUpdated(object sender, ImageUpdateEventArgs e) 
{ 
    e.img.Freeze(); // call here or in the ImageUpdateEventArgs constructor

    Dispatcher.Invoke(() => MyImageControl.Source = e.img);
}

Подробную информацию см. в разделе «Примечания» в Freezable.Freeze и Freezable.IsFrozen.

Это действительно решено. Однако у меня есть несколько вопросов: поскольку я сделал новую копию BitmapSource, и она взята из другого фонового потока, вызывающего диспетчеризацию... почему нам нужно ее заморозить, чтобы она была потокобезопасной? Я удалил спящий режим и заметил, что частота кадров невысокая. Однако с WriteableBitmap еще не удалось справиться.

Sean Tan 15.07.2024 10:14

Да, замораживание делает его доступным для всех потоков. Пожалуйста, прочитайте связанную документацию.

Clemens 15.07.2024 10:18

ирония заключается в том, что замечание никогда не предполагает совместного использования/цели: «Чтобы избежать возможности возникновения исключения InvalidOperationException при вызове этого метода, проверьте свойство CanFreeze, чтобы определить, можно ли сделать Freezable неизменяемым перед вызовом этого метода».

Sean Tan 15.07.2024 10:26

Кстати, при назначении свойства Source у вас должно было возникнуть исключение InvalidOperationException.

Clemens 15.07.2024 10:34

Интересная часть: вообще этого не видел.

Sean Tan 15.07.2024 11:53

Другие вопросы по теме