简体   繁体   English

后台线程中的 grpc 服务器 c++

[英]grpc Server in background thread c++

I am trying to run an grpc server in a thread in an MFC app.我正在尝试在 MFC 应用程序的线程中运行 grpc 服务器。

I have (grpc parts straight from the GRPC example):我有(直接来自 GRPC 示例的 grpc 部分):

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.没有线程,它运行良好(客户端可以连接并调用SayHello ),但由于grpcServer->Wait()调用而阻塞了RunServer()处的构造函数。 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用线程尝试它,我得到一个编译器错误: 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.不调用grpcServer->Wait()会导致服务器在RunServer()退出后立即关闭,尽管只要 class 实例正在运行,变量grpcServer仍然在 scope 中。

How do I properly start a grpcServer and put it in the background?如何正确启动grpcServer并将其置于后台?

I think the problem is this line within MyAppDlg::RunServer() :我认为问题在于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.您正在定义一个名为grpcServer的局部变量,而不是分配给同名的 class 数据成员,因此一旦RunServer()返回,它就会离开 scope 。 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":您需要将 RunServer 方法与 object 实例相关联,在本例中为“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.正如马克指出的那样,你有一个 class 成员 grpcServer,但是你在 RunServer 中声明了一个局部变量 grpcServer,它在 RunServer 退出后退出 scope。

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 .更重要的是,即使您在 RunServer 中执行Wait()并在单独的线程上运行它(应该可以正常工作), MyAppDlg::~MyAppDlg()也不会关闭服务器,因为它会关闭MyAppDlg::grpcServer ,这与 RunServer 内部的局部变量grpcServer RunServer

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM