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
来处理命令和响应。自定义网络协议非常复杂,如果您不熟悉异步代码,它们会更加复杂。
我有一个表单应用程序和一个与 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
来处理命令和响应。自定义网络协议非常复杂,如果您不熟悉异步代码,它们会更加复杂。