Visual C++/CLI, ThreadStart with a function pointer - multithreading

I am working on managed C++ or C++/CLI. I am trying to start a CLI thread to execute a function. However when I try to build I get the error "Microsoft (R) C/C++ optimizing compiler has stopped working." In the output window. "Foo.cpp(8): fatal error C1001: An internal error has occurred in the compiler."
//the class which holds the function to run
ref class Foo
{
void handleEvent();
void (*func)(void);
};
void Foo::handleEvent()
{
ThreadStart ^ param = gcnew ThreadStart(func); //line 8
Thread ^ thread = gcnew Thread(param);
thread.Start();
}
Is ThreadStart not capable of handling native function pointers? If not, is there is another way to run a regluar C function pointer from C++/CLI?

Try substituting line 8 with
ThreadStart^ param = (ThreadStart^) System::Runtime::InteropServices::Marshal::GetDelegateForFunctionPointer((IntPtr)func, ThreadStart::typeid);

Related

How to solve "Cross-thread operation not valid" in Visual C++/CLI

I have an issue (Windows Forms, C++, .NET) like this:
When I am trying to modify any WinForms object element (label, button etc) from a manage thread, I get the following error:
Sample Code:
static void myThread(System::Object^ obj, int nSocket) {
while (true) {
MyForm^ ob = (MyForm^)obj;
char buff[256 + 1] = { 0, };
recv(nSocket, buff, 255, 0);
string recvStr(buff);
ob->label3->Text = gcnew String(recvStr.c_str());
}
}
Exception thrown:
'System.InvalidOperationException' in System.Windows.Forms.dll
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll
Cross-thread operation not valid: Control 'label3' accessed from a thread other than the thread it was created on.
How to solve that issue in C++/CLI?

starting std::thread with anonymous class call

I am curious as to how to correctly start a std::thread using an anonymous class call.
With the below code, if my class only having 1 member variable and I call std::thread td(someclass(shared_mutex)); I get a compiler warning of warning
C4930: 'std::thread td(someclass)': prototyped function not called (was a variable definition intended?)
However, if I add a second member variable as below and call it with
std::thread td(someclass(shared_mutex,x));
I get an error with error C2064: term does not evaluate to a function taking 0 arguments.
class someclass
{
private:
std::mutex& shared_mutex;
int x;
public:
someclass(std::mutex& init_mutex, int init_x) :
shared_mutex(init_mutex),
x(init_x)
{}
//...
};
int main()
{
std::mutex shared_mutex;
int x = 10;
std::thread td(someclass(shared_mutex,x));
td.join();
return 0;
}
The only way around this is by creating an
void operator()()
{}
within the class, but is that the correct method, just to have some kind of starting function for the thread reference or am I missing some other point here? I thought the constructor would be resolver for that?
Try using { and } syntax to construct your object to avoid veximg parses as a function declaration.
std::thread td(someclass(shared_mutex,x))
becomes
std::thread td{someclass{shared_mutex,x}}
It seems that you want your thread to execute the long-running constructor of someclass and then immediately discard the newly constructed someclass. This can be done by passing the thread constructor a function object that does just that:
int main()
{
std::mutex shared_mutex;
int x = 10;
std::thread td([&]{someclass(shared_mutex,x);});
td.join();
return 0;
}
Be warned: constructing a new thread is a hugely expensive operation, so you should avoid casually spawning new threads if you have the ability to instead reuse existing threads, unless you are only going to create new threads very infrequently.

Console output from thread

I've just started experiencing with thread and can't get some basics. How can i write to Console from thread with interval say 10 msec? So i have a thread class:
public ref class SecThr
{
public:
DateTime^ dt;
void getdate()
{
dt= DateTime::Now;
Console::WriteLine(dt->Hour+":"+dt->Minute+":"+dt->Second);
}
};
int main()
{
Console::WriteLine("Hello!");
SecThr^ thrcl=gcnew SecThr;
Thread^ o1=gcnew Thread(gcnew ThreadStart(SecThr,&thrcl::getdate));
}
I cannot compile it in my Visual c++ 2010 c++ cli, get a lot of errors C3924, C2825, C2146
You are just writing incorrect C++/CLI code. The most obvious mistakes:
missing using namespace directives for the classes you use, like System::Threading, required if you don't write System::Threading::Thread in full.
using the ^ hat on value types like DateTime, not signaled as a compile error but very detrimental to program efficiency, it will cause the value to be boxed.
not constructing a delegate object correctly, first argument is the target object, second argument is the function pointer.
Rewriting it so it works:
using namespace System;
using namespace System::Threading;
public ref class SecThr
{
DateTime dt;
public:
void getdate() {
dt= DateTime::Now;
Console::WriteLine(dt.Hour + ":" + dt.Minute + ":" + dt.Second);
}
};
int main(array<System::String ^> ^args)
{
Console::WriteLine("Hello!");
SecThr^ thrcl=gcnew SecThr;
Thread^ o1=gcnew Thread(gcnew ThreadStart(thrcl, &SecThr::getdate));
o1->Start();
o1->Join();
Console::ReadKey();
}

Boost library and CreateThread win API

I have a class such as :
class MyStreamReader
{
public:
MyStreamReader(MyPramameter myPram) {.....}
~MyStreamReader() {}
DWORD WINAPI ReaderThread(LPVOID *lpdwThreadParam )
{
//....
}
};
and i want to call ReaderThread with WinAPI CreateThread. But CreateThread wants ReaderThread function wants a static function.
In some forms it is said that this is possible with boost library such as :
CreateThread(NULL, 0, boost::bind(&MyStreamReader::ReaderThread,this),
(void*)&myParameterObject), 0, NULL);
But i got compilation error:
'CreateThread' : cannot convert parameter x from 'boost::_bi::bind_t<R,F,L>'
to 'LPTHREAD_START_ROUTINE'
So as a result my questions:
Is it possible to call non-static function of a class from
CreateThread using boost lib(or any other method)
If not any C++ THREADing librray you may recomend(for visual C++) which i can call-run non static member function of a class as a thread?
Best Wishes
Update:
So first question: It seesm that it is impossible to call non-static c++ member function from CreateThread win API...
So any recomandations for C++ Multithreading lib whic is possible to call non-static functions as threads...
Update 2:
Well i try boost thread lib...seems it works...
MyStreamReader* streamReader = new MyStreamReader(myParameters);
boost::thread GetStreamsThread
( boost::bind( &MyStreamReader::ReaderThread, streamReader ) );
or (no need for bind)
boost::thread GetStreamsThread(&MyStreamReader::ReaderThread, streamReader);
AND in order to use boost::thread i update my class definition as:
class MyStreamReader
{
public:
MyStreamReader(MyPramameter myPram) {.....}
~MyStreamReader() {}
void ReaderThread()
{
//....
}
};
One common answer to this is to use a static "thunk":
class Worker
{
public :
static DWORD Thunk(void *pv)
{
Worker *pThis = static_cast<Worker*>(pv);
return pThis->DoWork();
}
DWORD DoWork() { ... }
};
...
int main()
{
Worker worker;
CreateThread(NULL, 0, &Worker::Thunk, &worker);
}
You can, of course, pack more parameters into your call to pv. Just have your thunk sort them out correctly.
To answer your question more directly, boost::bind doesn't work with the Winapi that way. I would advise using boost::thread instead, which does work with boost::bind (or, if you have a C++0x compiler, use std::thread with std::bind).

boost:thread - compiler error

I wanted to use boost::thread in my program, but get the following compiler error (Visual Studio 2005):
Error 1 **error C2064**: term does not evaluate to a function taking 0
arguments d:\...\boost_1_37_0\boost\thread\detail\thread.hpp 56
Therefore I tried to recreate the problem in a small program and modified the working Hello World example from this site.
My test code now looks like this. Why is it not working inside a class?:
#include <boost/thread.hpp>
#include <iostream>
class HelloWorld
{
public:
void hello();
void entry();
};
void HelloWorld::entry()
{
boost::thread thrd(&HelloWorld::hello);
thrd.join();
}
void HelloWorld::hello()
{
std::cout << "Hello world, I'm a thread!" << std::endl;
}
int main(int argc, char* argv[])
{
HelloWorld *bla = new HelloWorld;
bla->entry();
return 0;
}
Try it like this - the boost::thread constructor is expecting a boost::function0 (which a function pointer is, but a member function pointer isn't, due to the this pointer).
void HelloWorld::entry()
{
boost::thread thrd(boost::bind(&HelloWorld::hello,this));
thrd.join();
}
Member functions have a this pointer as the first argument. Since there is a boost::thread constructor that accepts function arguments, you don't need to use boost::bind. This will also work:
void HelloWorld::entry()
{
boost::thread thrd(&HelloWorld::hello,this);
thrd.join();
}
If your function requires arguments, you can put them after the this pointer argument.
You are passing a member function to the thread object as the function to call when the thread starts. Since the thread doesn't have the object itself, it can't call the member function. You could make the hello function static, or look at the boost::bind library to send in the object.

Resources