c# 在 TCPClient 异步接收数据时进行 UI 调用

c# make UI calls when TCPClient receives data async

我有一个表单应用程序和一个与 TCPClient 连接的控制台服务器应用程序。 Forms 应用程序打开一个用于用户身份验证的对话框,当用户单击“登录”按钮时,请求将发送到服务器。然后服务器响应登录凭据是否有效。 Forms 应用程序异步接收响应并发出错误消息或关闭身份验证 window 并继续。

阅读 this post 关于 SynchronizationContext 后,我创建了一个工作解决方案,它从处理服务器响应的线程调用 UI 线程上的函数。我的问题是,在 C# 中是否有更好的方法来执行此操作?

我在 async/await 上读了很多,但还没有找到等待特定服务器响应的方法。客户端使用来自缓冲区的 stream.BeginRead() 处理响应。

正在捕获 UI 上下文:

public static SynchronizationContext uiContext;

public MainForm(string[] args)
{
    InitializeComponent();
}

private void MainForm_Load(object sender, EventArgs e)
{
    uiContext = SynchronizationContext.Current;
    //etc
}

当客户端通过 stream.BeginRead() 接收到特定的服务器响应以进行身份​​验证时调用 LoginForm 上的函数:

private void UserAuthenticationAnswerReceived(byte[] _data)
{
    SynchronizationContext uiContext = MainForm.uiContext;
    //if auth was unsuccessful, the data will be only 1 int in length
    if (_data.Length <= sizeof(int))
    {
        Debug.WriteLine("Authentication failed.");
        uiContext.Post(UserLogin.userLoginFrm.AuthUnsuccessfulAsync, null);
    }
    else
    {
        Debug.WriteLine("Authentication successful.");
        uiContext.Post(UserLogin.userLoginFrm.AuthSuccessfulAsync, user);
    }
}

我对网络还很陌生,可能缺少关于 client/server 模型以及如何异步管理响应的更基本概念。

My question is, is there a better way to do this in C#?

一般来说,使用基于任务的 API(例如 ReadAsync)比使用旧式的基于 IAsyncResult 的 API(例如 BeginRead.

更容易

但对于从后台线程通知 UI 的一般解决方案,最好的解决方案是捕获 SynchronizationContext.

但是,如果你有一个 command/response 协议,客户端只接收它发送的命令的响应,那么你可以使用 async/await 得到一个更简单的解决方案.

I am quite new to networking and may be missing a more fundamental concept about client/server model and how to manage responses asynchronously.

我建议的第一件事是自行托管 ASP.NET Core WebApi。然后你可以使用现成的 HttpClient 来处理命令和响应。自定义网络协议非常复杂,如果您不熟悉异步代码,它们会更加复杂。