如何在一个线程中使用“this”!

时间:2011-04-05 09:10:29

标签: multithreading visual-studio-2010 visual-c++ c++-cli

我试图使用一个单独的线程调用我的静态函数,我的函数中有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 \ documents \ visual studio 2010 \ projects \ testscan \ testscan \ Form1.h 117

     

错误1错误C2273:'function-style cast':非法作为' - &gt;'的右侧运算符c:\ users \ ahmed \ documents \ visual studio 2010 \ projects \ testscan \ testscan \ Form1.h 105

     

错误2错误C2227:' - &gt; listBox1'的左侧必须指向类/ struct / union / generic类型c:\ users \ ahmed \ documents \ visual studio 2010 \ projects \ testscan \ testscan \ Form1.h 105

     

错误3错误C2227:' - &gt;项'左侧必须指向类/ struct / union / generic类型c:\ users \ ahmed \ documents \ visual studio 2010 \ projects \ testscan \ testscan \ Form1.h 105

     

错误4错误C2227:左边的' - &gt;添加'必须指向类/ struct / union / generic类型c:\ users \ ahmed \ documents \ visual studio 2010 \ projects \ testscan \ testscan \ Form1.h 105

3 个答案:

答案 0 :(得分:3)

无需使您的功能保持静态。给定错误是由于您使用的语法错误。 假设您的表单类型为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小伙子说的话。他说的很好。

答案 1 :(得分:2)

好的,基本原则:

  1. 静态表示该方法 NOT 是该对象的成员。它是Class类型的成员,并且与该类的所有对象相同。所以,没有这个,因为没有关联的对象。

  2. 读取编译器错误。阅读函数定义以传递正确的参数......

  3. 当你使用它时,你可能会遇到错误,因为你试图从另一个线程使用GUI函数。这将导致运行时错误(有时)。

  4. 请检查:UI Thread .Invoke() causing handle leak?

答案 2 :(得分:1)

免责声明:我没有使用过托管C ++,只有C#和vanilla C ++。因此,这个答案可能不正确。

ThreadStart委托可以参数。将类的实例传递给它并将其转换为静态线程方法中的类。它不是this,而是几乎相同的东西。