Как вы выполняете делегата в .Net C++

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

delegate void MyDel();
public ref class Form1 : public System::Windows::Forms::Form
{
    // .....
    void testFunc()
    {
       this->local_long_textBox->Text = "Test!!!!!!!";
    }
private:
    void startUp()
    {
       MyDel^ DelInst = gcnew MyDel(this,&CotStinger::Form1::testFunc);

Я хотел бы передать DelInst другому потоку при создании, но когда я пытаюсь объявить MyDel как внешний вид, подобный этому, поверх другого модуля:

extern delegate MyDel;

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

Ошибка C2146: синтаксическая ошибка: отсутствует ';' перед идентификатором 'MyDel'.

Если я попробую это

extern delegate void MyDel();

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

Ошибка C2144: синтаксическая ошибка: 'void' должно предшествовать ';'

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


person user758362    schedule 21.06.2011    source источник


Ответы (1)


Ключевое слово delegate используется для определения типа делегата, а не для объявления переменной, которая является некоторым типом делегата. То есть, как только тип делегата определен, ключевое слово delegate больше не нужно.

Кроме того, глобальные переменные управляемых типов не разрешены в C++/CLI; обычный обходной путь — использовать логически-статический управляемый класс с общедоступными статическими элементами данных, которые функционируют как глобальные:

delegate void MyDel();
private ref struct Globals abstract sealed
{
    static MyDel^ MyDelInstance;
};

// ...

Globals::MyDelInstance = gcnew MyDel(this, &CotStinger::Form1::testFunc);

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

То же, что и с любым другим типом — поместите его в заголовочный файл, который оба класса могут #include.

person ildjarn    schedule 22.06.2011
comment
Я скопировал ваш код выше и получил следующее сообщение: ошибка C3145: 'myDelInstance': глобальная или статическая переменная, возможно, не имеет управляемого типа 'CotStinger::MyDel ^' - person user758362; 22.06.2011
comment
Остальная часть сообщения: нельзя объявлять глобальную или статическую переменную или член собственного типа, который ссылается на объекты в куче gc. - person user758362; 22.06.2011
comment
Да! Так что же делает абстрактная запечатанная структура ref struct Globals? - person user758362; 22.06.2011
comment
@user758362 user758362 : Если вы знаете C#, это точный эквивалент static class в C#, за исключением того, что по умолчанию он имеет общедоступный доступ к членам, а не частный. То есть, это управляемый тип с доступом к общедоступным членам по умолчанию, который не может быть получен или создан (и поэтому фактически может иметь только static данных-членов и функций-членов). - person ildjarn; 22.06.2011
comment
Хорошо, я включил файл Form1.h с приведенными выше объявлениями в свой второй модуль, и у меня возникли трудности с его компиляцией. Какой синтаксис я бы использовал во втором модуле. Пишет, что не найдено. - person user758362; 22.06.2011
comment
@user758362 user758362: Вы говорите, что ваш файл Form1.h содержит определения MyDel и Globals, а какой-то второй файл включает Form1.h, но вы не можете найти определения этих типов? Я тебе не верю. ;-] - person ildjarn; 22.06.2011
comment
Я понял. Мне нужно было разделить делегатов на их собственный файл .h. Включение файла пользовательского интерфейса .h везде вызывало проблемы. - person user758362; 22.06.2011
comment
@ildjarn, почему я не могу предварительно объявить делегата так же, как я могу предварительно объявить другие управляемые типы? stackoverflow.com/questions/1005892/ - person Agnel Kurian; 02.08.2013