0

I'm new to threads and Winforms/C++. I would like to start a function in a new thread when I press a button. I was following this as a tutorial for threads. When I build the example code given on that site in a separate VC++ project, the build succeeds.

However, if I do the following in my C++/Winforms the build won't complete, I get a build error.

What am I missing here?

Help!

Code:

void  Test( void *arg );
private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e)
         {
                    _beginthread(Test, 0, (void*)12);
         }
void  Test( void *arg )
{
    // Do something
}

Build ERROR:

Error   1   error C2664: '_beginthread' : cannot convert parameter 1 from 'void (__clrcall *)(void *)' to 'void (__cdecl *)(void *)'    c:\users\documents\visual studio 2010\projects\statsv2.0\statsv2.0\Form1.h  659 1   StatsV2.0
HaggarTheHorrible
  • 7,083
  • 20
  • 70
  • 81

1 Answers1

2

You're using managed C++ (C++/CLR). This is very different from native C++ (which the tutorial was written for).

In managed C++, the default calling convention is not compatible with the calling convention of the function pointer that the native _beginthread function is expecting. Fortunately, managed C++ has very good interop with native C++, and changing your function declaration to the following should work:

void __cdecl Test( void *arg )

Since you're using managed C++, you have the full power of .NET on your side, and could instead create managed threads (e.g. with a Task object).

Note also that any win32 UI object created on the main thread must only be accessed on that thread -- so be careful! :-)

Cameron
  • 96,106
  • 25
  • 196
  • 225
  • Thanks for you quick reply :-). If I make the change you suggested I still get a build error as: Error 1 error C2062: type 'void' unexpected. Pointing to the Test function prototype. – HaggarTheHorrible Feb 20 '13 at 05:01
  • @Haggar: Oops, I seem to have put the calling convention in the wrong spot! You can also enclose the function in `#pragma unmanaged` ... `#pragma managed`. – Cameron Feb 20 '13 at 05:04
  • I did this #pragma unmanaged __cdecl void Test( void *arg ) { //Do something } #pragma managed. But I still get: type 'void' unexpected. – HaggarTheHorrible Feb 20 '13 at 05:11
  • @Haggar: Yes, as I said I had accidentally put the calling convention in the wrong spot, sorry (my edit fixed it). `__cdecl` should go in between the return type and the function name, not before. And I don't think you need to enclose the function with the pragmas; specifying the `__cdecl` should be enough (if it's not, then you can add the pragmas, but you'll lose the ability to interop with .NET within the function). – Cameron Feb 20 '13 at 08:07
  • Thanks. It works now. There was /clr related issue, which I fixed in the project settings. Thank you once again :-) – HaggarTheHorrible Feb 20 '13 at 08:32