Как использовать «это» в потоке! - PullRequest
0 голосов
/ 05 апреля 2011

Я пытаюсь вызвать мою статическую функцию, используя отдельный поток, в моей функции есть что-то вроде this->listBox1->Items->Add(s);. Компилятор показывает, что я не могу использовать this внутри статической функции. Я пытался сделать свою функцию нестатичной (т.е. удалить ключевое слово static), но когда я это сделал, снова компилятор показывает две ошибки:

Ошибка 2: ошибка C3350: 'System :: Threading :: ThreadStart': конструктор делегата ожидает 2 аргумента (ов) c: \ users \ ahmed \ documents \ visual studio 2010 \ projects \ testscan \ testscan \ Form1.h 116

Ошибка 1, ошибка C2276: '&': недопустимая операция с выражением функции связанного члена c: \ users \ ahmed \ Documents \ visual studio 2010 \ projects \ testscan \ testscan \ Form1.h 116


Редактировать

Функция:

void ScanMyDir(String^ SourceDir)
{
    array <String^> ^fileEntries = Directory::GetFiles(SourceDir);
    for each (String^ fileName in fileEntries)
        this->Form1->listBox1->Items->Add(fileName);

    array<String^> ^SubDirEntries = Directory::GetDirectories(SourceDir);
    for each (String^ subdir in SubDirEntries)
        if ((File::GetAttributes(subdir) & FileAttributes::ReparsePoint)!= FileAttributes::ReparsePoint)
            ScanMyDir(subdir);
}

Как это назвать:

void button1_Click(System::Object^  sender, System::EventArgs^  e) {
    Thread ^thr1 = gcnew Thread(gcnew ParameterizedThreadStart(this,&Form1::ScanMyDir));
    thr1->Start("c:\\"); 
}

Модификация при загрузке формы:

void Form1_Load(System::Object^  sender, System::EventArgs^  e) {
    System::Windows::Forms::Control::CheckForIllegalCrossThreadCalls = false;
}

Новые ошибки :(:

Ошибка 5 Ошибка C3352: «void testScan :: Form1 :: ScanMyDir (System :: String ^)»: указанная функция не соответствует типу делегата «void (System :: Object ^)» c: \ users \ ahmed \ документация \ visual studio 2010 \ projects \ testscan \ testscan \ Form1.h 117

Ошибка 1 ошибка C2273: «приведение в стиле функции»: недопустимо в правой части оператора «->» оператор c: \ users \ ahmed \ Documents \ visual studio 2010 \ projects \ testscan \ testscan \ Form1.h 105

Ошибка 2: ошибка C2227: слева от '-> listBox1' должен указываться тип / структура / объединение / универсальный тип c: \ users \ ahmed \ documents \ visual studio 2010 \ projects \ testscan \ testscan \ Form1.h 105

Ошибка 3 Ошибка C2227: слева от '-> Элементы' должен указываться класс / структура / объединение / универсальный тип c: \ users \ ahmed \ Documents \ visual studio 2010 \ projects \ testscan \ testscan \ Form1.h 105

Ошибка 4: ошибка C2227: слева от '-> Добавить' должен указываться класс / структура / объединение / универсальный тип c: \ users \ ahmed \ Documents \ visual studio 2010 \ projects \ testscan \ testscan \ Form1.h 105

Ответы [ 3 ]

3 голосов
/ 05 апреля 2011

Нет необходимости делать вашу функцию статичной. Данные ошибки связаны с неправильным синтаксисом, который вы используете. Принимая ваш тип формы как FormType,

void ScanMyDir()
{
//....
}

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) 
{
  Thread ^thr1 =gcnew Thread(gcnew ThreadStart(this,&FormType::ScanMyDir));
  thr1->Start();       
}

Если вы настаиваете на том, чтобы сделать его статическим, как сказал @jgauffin, передайте форму в качестве параметра Object в ScanMyDir() и затем переделайте ее в форму в функции.

static void ScanMydir(Object ^ param)
{
  FormType ^ ft = static_cast<FormType^>(param); 
  //..
  ft->listBox1->Items->Add(fileName);
  //..
}

В этом случае вы должны использовать ParametrizedThreadStart()

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) 
    {
      Thread ^thr1 =gcnew Thread(gcnew ParametrizedThreadStart(&FormType::ScanMyDir));
      // it is static no need for "this"
      thr1->Start(this);       
    }

Но, по крайней мере, сделайте функцию ScanMyDir() частной и запретите доступ извне.

Теперь, вероятно, у вас будет другая ошибка: «Вы не можете касаться GUI разными потоками», затем в функцию загрузки форм напишите

void FormType_Load(Object ^sender, EventArgs ^ e)
{
  System::Windows::Forms::Control::CheckForIllegalCrossThreadCalls = false;
  //....
}

Но это может быть опасно в зависимости от вашей реализации, вы должны гарантировать безопасность потоков listbox1->items.

Также послушайте, что сказал парень @Yochai Timmer. Он говорит хорошие вещи.

2 голосов
/ 05 апреля 2011

Хорошо, основные принципы:

  1. Статический означает, что метод НЕ является членом объекта.Он является членом типа Class и является общим для всех объектов этого класса.Таким образом, нет этого , поскольку с ним не связан ни один объект.

  2. Считайте ошибки компилятора.Прочитайте определения функций для передачи правильных параметров ...

  3. Когда вы заработаете эту работу, у вас, вероятно, будет ошибка, потому что вы пытаетесь использовать функции GUI из другого потока,Это приведет к ошибкам во время выполнения (иногда).

Проверьте это: Поток интерфейса. Invoke (), вызывающий утечку из ручки?

1 голос
/ 05 апреля 2011

Отказ от ответственности: я не использовал управляемый C ++, только C # и vanilla C ++. Поэтому этот ответ может быть неверным.

ThreadStart делегат может принимать параметр. Передайте ему экземпляр вашего класса и приведите его к вашему классу в методе static thread. Это не this, но почти то же самое.

...