我希望干净地关闭我的表单应用程序,同时正在进行grpc通话。我认为ShutdownAsync会关闭所有正在进行的通话,但似乎我没有把它放在正确的地方,或者它不负责关闭频道。什么是实现全能的最简单方法,在应用程序关闭时以CompleteAsync()
结束所有流?
我使用另一个类来保存所有grpc的东西还有一个额外的困难,我不知道什么时候收集垃圾。当然,我可以做一个取消令牌并在我关闭时取消所有正在进行的通话,但同样,我应该在哪里取消?在Model的析构函数或View的析构函数中?
示例代码:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Grpc.Core;
using OdinIntegrationSyncRPC;
namespace MinViaExample
{
public partial class Form1 : Form
{
ExampleModel ex;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ex = new ExampleModel();
}
private void Form1_Shown(object sender, EventArgs e)
{
ex.Sync();
}
private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
await ex.ShutdownChannelAsync();
}
}
public class ExampleModel
{
Channel channel;
OdinIntegrationSync.OdinIntegrationSyncClient client;
private AsyncDuplexStreamingCall<LSHeartbeat, LastStudentsPacket> CurrentCall;
public ExampleModel()
{
channel = new Channel("127.0.0.1:50052", ChannelCredentials.Insecure);
client = new OdinIntegrationSync.OdinIntegrationSyncClient(channel);
}
public async void Sync()
{
var CTokenSource = new CancellationTokenSource();
CancellationToken CToken = CTokenSource.Token;
using (CurrentCall = client.GetLastStudentSync())
{
await CurrentCall.RequestStream.WriteAsync(new LSHeartbeat() { ContinueRequest = true });
while (await CurrentCall.ResponseStream.MoveNext(CancellationToken.None) && !CToken.IsCancellationRequested)
{
LastStudentsPacket lsp = CurrentCall.ResponseStream.Current;
foreach (OStudent o in lsp.Students)
{
// blahblah
}
await CurrentCall.RequestStream.WriteAsync(new LSHeartbeat() { ContinueRequest = true });
}
}
await CurrentCall.RequestStream.CompleteAsync();
}
public async Task ShutdownChannelAsync()
{
await channel.ShutdownAsync();
}
}
}
编辑:上面的代码已从最初的问题(添加ShutdownChannel调用添加到FormClosing)更改。现在只有服务器崩溃System.InvalidOperationException: 'Already finished.'
。客户似乎干净利落地退出。
如果我错过了一些基本的东西,请道歉。