I am trying to run an grpc server in a thread in an MFC app.
I have (grpc parts straight from the GRPC example):
MyAppDlg.h:
#include <thread>
#include <grpcpp\grpcpp.h>
class MyAppDlg : public CDialog
{
public:
MyAppDlg( CString aFileName, CWnd *pParent = NULL );
virtual ~MyAppDlg();
std::unique_ptr<grpc::Server> grpcServer;
std::thread grpcThread;
void RunServer();
MyAppDlg.cpp:
class GreeterServiceImpl final : public Greeter::Service {
Status SayHello(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override {
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
return Status::OK;
}
};
void MyAppDlg::RunServer() {
std::string server_address("0.0.0.0:50051");
GreeterServiceImpl service;
grpc::EnableDefaultHealthCheckService(true);
grpc::reflection::InitProtoReflectionServerBuilderPlugin();
ServerBuilder builder;
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
std::unique_ptr<Server> grpcServer(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
// Wait for the server to shutdown. Note that some other thread must be
// responsible for shutting down the server for this call to ever return.
grpcServer->Wait(); <-- Leaving this out causes the server to close immediately again.
}
MyAppDlg::MyAppDlg( CString aFileName, CWnd* pParent /* =NULL */ )
{
... stuff ...
// RunServer(); <-- using this works but blocks the thread
grpcThread(RunServer); <-- does not work
}
MyAppDlg::~MyAppDlg()
{
grpcServer->Shutdown();
grpcThread.join();
}
Without the thread, it runs fine (client can connect and call SayHello
), but blocks the constructor at RunServer()
because of the grpcServer->Wait()
call. Trying it with the thread, I get a compiler error: call of an object of a class type without appropriate operator() or conversion functions to pointer-to-function type
Not calling grpcServer->Wait()
causes the server to close immediately after RunServer()
exits, although the variable grpcServer
is still in the scope as long as the class instance is running.
How do I properly start a grpcServer
and put it in the background?
I think the problem is this line within MyAppDlg::RunServer()
:
std::unique_ptr<Server> grpcServer(builder.BuildAndStart());
You're defining a local variable called grpcServer
instead of assigning to the class data member of the same name, so it's going out of scope as soon as RunServer()
returns. I think that should just be:
grpcServer.reset(builder.BuildAndStart());
If you want to run the server in a separate thread, that is the
grpcThread(Runserver);
You need to associate the RunServer method with an object instance, in this case "this":
grpcTread(std::bind(&MyAppDlg::RunServer, this));
This should fix the compilation error.
And as Mark pointed out, you have a class member grpcServer, but you declare a local variable grpcServer in RunServer which goes out of scope after RunServer exits.
What's more, even if you do the Wait()
inside RunServer and run it on a separate thread (which should work just fine), the MyAppDlg::~MyAppDlg()
will not shutdown the server since it will shutdown the MyAppDlg::grpcServer
, which is different from the local variable grpcServer
inside RunServer
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.