C# WPF.NET内核中的gRPC错误
我想创建一个简单的WPF核心gRPC项目。这个“代码”在我的.NET核心控制台应用程序中运行得非常好,不过WPF似乎有些特别 原始文件 gRPC服务器 在Visual Studio 2019中创建了默认模板(使用.NET Core 3.1) 控制台应用程序(工作完美) 创建了一个默认的.NET Core控制台应用程序->将原始文件从服务器添加到客户端,并将gRPC存根类更改为仅客户端 用法:.NET Core 3.1 具有以下NUGET:C# WPF.NET内核中的gRPC错误,c#,wpf,grpc,C#,Wpf,Grpc,我想创建一个简单的WPF核心gRPC项目。这个“代码”在我的.NET核心控制台应用程序中运行得非常好,不过WPF似乎有些特别 原始文件 gRPC服务器 在Visual Studio 2019中创建了默认模板(使用.NET Core 3.1) 控制台应用程序(工作完美) 创建了一个默认的.NET Core控制台应用程序->将原始文件从服务器添加到客户端,并将gRPC存根类更改为仅客户端 用法:.NET Core 3.1 具有以下NUGET: Grpc.工具 Grpc.Net.Client 谷歌
- Grpc.工具
- Grpc.Net.Client
- 谷歌
- Grpc.工具
- Grpc.Net.Client
- 谷歌
此问题与
Grpc.Tools
包和WPF应用程序的特殊构建过程有关。Grpc.Tools
包负责编译.proto文件并生成服务类
解决方案是将gRPC客户端实例化移动到单独的.NET核心类库程序集(项目)中。只需将此代码提取到此新程序集中的类,例如,GrpcServiceProvider
。让GrpcServiceProvider
返回gRPC客户端的实例。现在从您的WPF程序集引用.NET核心库程序集和GrpcServiceProvider
类,以获取客户端实例。这将修复构建错误并改进应用程序设计 不要忘记,
GrpcChannel
实现了IDisposable
。这意味着GrpcServiceProvider
也应该实现它,并正确地配置它的资源
.NET核心类库项目
public class GrpcServiceProvider : IDisposable
{
public GrpcServiceProvider()
{
this.ServiceUrl = "https://localhost:5001";
this.DefaultRpcChannel = new Lazy<GrpcChannel>(GrpcChannel.ForAddress(this.ServiceUrl));
}
public Greeter.GreeterClient GetGreeterClient() => this.GreeterClient ??= new Greeter.GreeterClient(this.DefaultRpcChannel.Value);
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
if (this.DefaultRpcChannel.IsValueCreated)
{
this.DefaultRpcChannel.Value.Dispose();
}
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
// ~GrpcServiceProvider()
// {
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
// }
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion IDisposable Support
private Lazy<GrpcChannel> DefaultRpcChannel { get; set; }
private string ServiceUrl { get; set; }
private Greeter.GreeterClient GreeterClient { get; set; }
}
Loaded += async delegate
{
using var serviceProvider = new GrpcServiceProvider();
var client = serviceProvider.GetGreeterClient();
var reply = await client.SayHelloAsync(new HelloRequest { Name = "GreeterClient" });
};
您在哪里定义了
.proto
文件?console应用程序的项目文件与WPF应用程序的项目文件有什么区别?@mm8我在每个项目中定义了我的proto文件(例如WPF有他的proto,console有他自己的proto等等)。关于你的第二个问题:没什么,它们都只是客户端,我的grpc服务器原型也有相同的内容,但它只是服务器。
Loaded += async delegate
{
using var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = "GreeterClient" });
};
public class GrpcServiceProvider : IDisposable
{
public GrpcServiceProvider()
{
this.ServiceUrl = "https://localhost:5001";
this.DefaultRpcChannel = new Lazy<GrpcChannel>(GrpcChannel.ForAddress(this.ServiceUrl));
}
public Greeter.GreeterClient GetGreeterClient() => this.GreeterClient ??= new Greeter.GreeterClient(this.DefaultRpcChannel.Value);
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
if (this.DefaultRpcChannel.IsValueCreated)
{
this.DefaultRpcChannel.Value.Dispose();
}
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
// ~GrpcServiceProvider()
// {
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
// }
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion IDisposable Support
private Lazy<GrpcChannel> DefaultRpcChannel { get; set; }
private string ServiceUrl { get; set; }
private Greeter.GreeterClient GreeterClient { get; set; }
}
Loaded += async delegate
{
using var serviceProvider = new GrpcServiceProvider();
var client = serviceProvider.GetGreeterClient();
var reply = await client.SayHelloAsync(new HelloRequest { Name = "GreeterClient" });
};