0

I am trying to call my static function using a separate thread, I have in my function something like this->listBox1->Items->Add(s);. The compiler shows that I can't use this inside a static function. I tried to make my function non-static (i.e remove static keyword) but when I did that, again the compiler shows two errors which are:

Error 2 error C3350: 'System::Threading::ThreadStart' : a delegate constructor expects 2 argument(s) c:\users\ahmed\documents\visual studio 2010\projects\testscan\testscan\Form1.h 116

Error 1 error C2276: '&' : illegal operation on bound member function expression c:\users\ahmed\documents\visual studio 2010\projects\testscan\testscan\Form1.h 116


Edit:

The function:

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);
}

Way to call it:

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

Modification on Form load:

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

The new errors :( :

Error 5 error C3352: 'void testScan::Form1::ScanMyDir(System::String ^)' : the specified function does not match the delegate type 'void (System::Object ^)' c:\users\ahmed\documents\visual studio 2010\projects\testscan\testscan\Form1.h 117

Error 1 error C2273: 'function-style cast' : illegal as right side of '->' operator c:\users\ahmed\documents\visual studio 2010\projects\testscan\testscan\Form1.h 105

Error 2 error C2227: left of '->listBox1' must point to class/struct/union/generic type c:\users\ahmed\documents\visual studio 2010\projects\testscan\testscan\Form1.h 105

Error 3 error C2227: left of '->Items' must point to class/struct/union/generic type c:\users\ahmed\documents\visual studio 2010\projects\testscan\testscan\Form1.h 105

Error 4 error C2227: left of '->Add' must point to class/struct/union/generic type c:\users\ahmed\documents\visual studio 2010\projects\testscan\testscan\Form1.h 105

Community
  • 1
  • 1
Aan
  • 12,247
  • 36
  • 89
  • 150
  • Not really your current problem, but it looks like you're trying to write to a GUI object from a non-GUI thread, which is generally considered a no-no... – forsvarir Apr 05 '11 at 09:13
  • You should show us the function declaration, line 116 , and tell us the scope (Where the function is declares (class declaration) ) – Yochai Timmer Apr 05 '11 at 09:15

3 Answers3

3

No need to make your function static. Given errors are due to the wrong syntax you are using. Assuming your form type as 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();       
}

If you insist on making it static, like @jgauffin said pass the form as an Object parameter to ScanMyDir() and then recast it to form in the function.

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

In this case you have to use 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);       
    }

But at least make the ScanMyDir() function private and prevent outside access.

Now probably you will have another error, saying "you can not touch GUI with different threads", then on your forms loading function write

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

But this may be dangerous depending on your implementation, you have to guarantee the thread-safety of listbox1->items.

Also listen to what the @Yochai Timmer guy said. He is telling good things.

ali_bahoo
  • 4,732
  • 6
  • 41
  • 63
  • alot of thanks sad_man .. no need to be sad man ! i did some of your notices and i have put what i did please see it .. it is still with errors !! – Aan Apr 05 '11 at 13:21
  • @user630908: Please read the usage of [ParametrizedThreadStart()](http://msdn.microsoft.com/en-us/library/system.threading.parameterizedthreadstart.aspx). Your function strictly must be `void ScanMyDir(Object^ param)`. You will cast this param to string like `String ^ mydir = (String^)param;` or `String ^mydir = param.ToString();` – ali_bahoo Apr 05 '11 at 13:31
  • Thanks Sad Man! I realized thats no need to pass "this", just directly use `listBox1->Items->Add(fileName);` NOT `this->Form1->listBox1->Items->Add(fileName);` and use of `CheckForIllegalCrossThreadCalls` was very helpful! Thank you again, and thanks also to all contributors. – Aan Apr 05 '11 at 18:55
2

Ok, basic principles:

  1. Static means that the method is NOT a member of the object. It's a member of the Class type, and is in common to all the objects of that class. So, there's no this because there's no object associated.

  2. Read the compiler errors. Read the function definitions to pass th right parameters...

  3. When you get this working, you'll probably have an error because you're trying to use GUI function's from a different thread. That will cause run-time errors (sometimes).

Check this: UI Thread .Invoke() causing handle leak?

Community
  • 1
  • 1
Yochai Timmer
  • 48,127
  • 24
  • 147
  • 185
1

Disclaimer: I haven't used managed C++, only C# and vanilla C++. Therefore this answer might be incorrect.

ThreadStart delegate can take a parameter. Pass the instance of your class to it and cast it to your class in the static thread method. It's not this, but almost the same thing.

jgauffin
  • 99,844
  • 45
  • 235
  • 372