2016-10-17 14 views
1

У меня есть класс MainForm (как и следовало ожидать, это форма), на котором есть текстовое поле. У меня также есть еще один класс под названием «Application_Server». Это делает загрузку другого материала (не только связанного с фоном, довольно много сетевого материала и т. Д.).C++ CLI Invoke issues

Класс Application_Server запускается в собственном потоке, но для обновления элементов управления в форме для этого вопроса мы будем придерживаться только текстового поля.

Проблема заключается в том, что даже если я выполнить команду, чтобы установить текст элемента управления TextBox с помощью «Invoke» Я до сих пор получаю следующее исключение во время выполнения:

Дополнительная информация: операции кросс-нить Недействительно: Управление 'DebugTextBox', доступ к которому осуществляется из потока, отличного от потока, который был создан .

Что может быть причиной этого? Я определенно приглашаю делегата в MainForm.

Вот соответствующие сегменты кода (вырублены для удобства чтения):

MainForm.h:

public ref class MainForm : public System::Windows::Forms::Form { 

     delegate void del_updateDebugText(String^ msg); 
     del_updateDebugText^ updateDebugText = gcnew del_updateDebugText(this, &MainForm::postDebugMessage); 

private: void postDebugMessage(String^ message); 
}; 

MainForm.cpp:

void EagleEye_Server::MainForm::postDebugMessage(String^ message) 
{ 
    Monitor::Enter(DebugTextBox); 
    if (this->DebugTextBox->InvokeRequired) 
    { 
     this->Invoke(updateDebugText, gcnew array<Object^> { message }); 
    } 
    else 
    { 
     this->DebugTextBox->AppendText(message); 
    } 
    Monitor::Exit(DebugTextBox); 
} 

И, наконец, код, вызывающий его :

void ServerAppManager::postDebugMessage(System::String^ message) 
{ 
    mainFormHandle->updateDebugText(message); 
} 

void ServerAppManager::applicationStep() 
{ 
    postDebugMessage("Starting\n"); 
    // This is Run in seperate thread in MainForm.cpp 
    while (s_appState == ApplicationState::RUN) 
    {  
     postDebugMessage("Testing\n");  
    } 

} 

Спасибо!

+0

Все кажется прекрасным, но вы вызываете 'Invoke()' с 'MainForm', а не' TextBox'. Вы можете попробовать вызвать 'Invoke()' с помощью 'TextBox', чтобы узнать, помогает ли это. Если это исправлено, это означает, что «TextBox» мог быть создан в другом потоке из «MainForm», что не кажется правильным. – Andy

+0

Не будет ли этот код заторможен? Вызов 'Invoke()' приведет к вызову 'postDebugMessage()' в потоке пользовательского интерфейса, что вызовет его ожидание на 'DebugTextBox', который удерживается вызывающим потоком ... – Medinoc

+0

Да, действительно, он зашел в тупик , из интереса, как бы вы сделали это аккуратно, чтобы этого не случилось? Мой пример ниже (нажатие вызова Invoke другому объекту, вызывающему метод) кажется беспорядочным, например, что, если я забыл вызвать? –

ответ

-1

мне удалось получить его работу путем упрощения метода в классе «MainForm» в:

void EagleEye_Server::MainForm::postDebugMessage(String^ message) 
{ 
    Monitor::Enter(DebugTextBox); 
    DebugTextBox->AppendText(message); 
    Monitor::Exit(DebugTextBox); 
} 

И затем двигается призывом «преведущей» методы вызова делегата, не очень, но это работает Теперь. Я думаю, что проблема может быть вызвана тем, что форма застревает внутри цикла Invoke. Я говорю об этом, поскольку заметил, что форма блокируется и перестает отвечать после того, как она попадает в рекурсивный оператор Invoke.

+0

Я не отметил это как ответ, так как я уверен, что это лучший способ решить эту проблему и хотел бы проголосовать за это как ответ, если кто-то опубликует решение. –