Asynchronous 在Asp Net核心服务中运行异步方法的位置
我有一个服务,它必须保持与数据库的实时连接。这个连接必须在任何客户端请求之前实例化 由于数据库API提供了一种异步连接方法,在发出任何请求之前,我在哪里可以连接到数据库 SocketMiddleware:Asynchronous 在Asp Net核心服务中运行异步方法的位置,asynchronous,.net-core,Asynchronous,.net Core,我有一个服务,它必须保持与数据库的实时连接。这个连接必须在任何客户端请求之前实例化 由于数据库API提供了一种异步连接方法,在发出任何请求之前,我在哪里可以连接到数据库 SocketMiddleware: class SocketMiddleware { Handler handler; public SocketMiddleware(Handler _handler,RequestDelegate del) { t
class SocketMiddleware
{
Handler handler;
public SocketMiddleware(Handler _handler,RequestDelegate del)
{
this.handler = _handler;
this.next = del;
}
RequestDelegate next;
public async Task Invoke(HttpContext context)
{
if (!context.WebSockets.IsWebSocketRequest)
{
await this.next(context);
return;
}
await this.handler.AddClientAsync(context.WebSockets);
}
}
使用实时DB
连接的服务:
class Handler
{
private readonly RethinkDB r;
public Connection Con { get; private set; }
private ConcurrentDictionary<string, Client> clients = new ConcurrentDictionary<string, Client>();
private object Lock = new object();
public Handler()
{
this.r = new RethinkDB();
//I have to instnatiate --- this.Con = this.r.Connection().Port(Constants.RETHINK_PORT).Hostname(Constants.HOST_NAME).ConnectAsync();
}
///////////////////////////---Where can i run the below method?
public async Task ConnectRethinkAsync()
{
using (Process proc = new Process())
{
proc.StartInfo = new ProcessStartInfo(Constants.RETHINK_PROCESS_PATH);
proc.Start();
this.Con = await this.r.Connection().Port(Constants.RETHINK_PORT).Hostname(Constants.HOST_NAME).ConnectAsync();
}
}
public async Task AddClientAsync(WebSocketManager manager)
{
WebSocket clientSocket = await manager.AcceptWebSocketAsync();
string clientID = Ext.MakeId();
using (Client newClient = Client.Create(clientSocket, clientID))
{
while (true)
{
if (!newClient.KeepAlive)
{
break;
}
ReadOnlyMemory<byte>received = await newClient.ReceiveAsync();
string toSend = $"From Server:\r\nDate:{DateTime.Now.ToString()},WasReceived:{Encoding.UTF8.GetString(received.ToArray())}\r\nEnd of Message\r\n";
// await r.Db(Constants.DB_NAME).Table(Constants.TABLE_NAME).RunAsync(this.Con);
await newClient.SendAsync(toSend);
}
}
}
public bool RemoveClient(string ID)
{
if (this.clients.TryRemove(ID, out Client value))
{
value.Dispose();
return true;
}
return false;
}
}
类处理程序
{
私有只读数据库;
公共连接Con{get;private set;}
私有ConcurrentDictionary客户端=新建ConcurrentDictionary();
私有对象锁=新对象();
公共处理程序()
{
this.r=newdb();
//我必须安装--this.Con=this.r.Connection().Port(常数.重新思考端口).主机名(常数.主机名).ConnectAsync();
}
///////////////////////////---在哪里可以运行下面的方法?
公共异步任务ConnectAsync()
{
使用(Process proc=new Process())
{
proc.StartInfo=新进程StartInfo(常数.重新思考进程路径);
proc.Start();
this.Con=wait this.r.Connection().Port(Constants.reference_Port)、Hostname(Constants.HOST_NAME)、ConnectAsync();
}
}
公共异步任务AddClientAsync(WebSocketManager)
{
WebSocket clientSocket=await manager.AcceptWebSocketAsync();
字符串clientID=Ext.MakeId();
使用(Client newClient=Client.Create(clientSocket,clientID))
{
while(true)
{
如果(!newClient.KeepAlive)
{
打破
}
ReadOnlyMemoryreceived=Wait newClient.ReceiveAsync();
string toSend=$“来自服务器:\r\n数据:{DateTime.Now.ToString()},wasserved:{Encoding.UTF8.GetString(received.ToArray())}\r\n消息的名称\r\n”;
//等待r.Db(Constants.Db_NAME).Table(Constants.Table_NAME).RunAsync(this.Con);
等待newClient.SendAsync(toSend);
}
}
}
public bool RemoveClient(字符串ID)
{
if(this.clients.TryRemove(ID,out客户端值))
{
value.Dispose();
返回true;
}
返回false;
}
}
注意:在上面的代码片段中,最重要的一行是带有注释的一行:我需要实例化连接,这是一个异步操作。我不能在
处理程序中实例化它,也不在SocketMiddleware
ctor中。
在执行任何请求之前必须初始化Con
。(在本例中,调用了addclientsync
)
数据库连接是否应该在其他服务中完成?因为您已经保护了要从外部设置的连接,所以可以在addclientsync
中恢复连接,如:
if(this.Con == null)
{
this.Con = await this.r.Connection()
.Port(Constants.RETHINK_PORT)
.Hostname(Constants.HOST_NAME)
.ConnectAsync();
}
使用目标方法初始化连接。它将在第一次调用时初始化,并在后续调用时返回连接。你说的懒惰是什么意思?除非调用其连接.ConnectAsync
方法,否则它是空的。方法端口
和主机名
返回的对象不是连接
类型。只有在运行ConnectAsync
时,我才能获得连接
,以及我创建的包装器方法除了我不想/不需要的每一个客户端请求之外,没有地方可以调用连接。但我不想污染AddClientSync
域,因为这是另一个问题。在创建处理程序时,数据库的连接
只执行一次,而AddClientSync
则对每个客户端执行一次websocket
accept。在处理程序
类中是否没有其他地方可以插入连接
(可能在Startup
类的层次结构中更高,特别是在Configure
或ConfigureServices
中?我这样问是因为将来处理程序可能需要其他依赖项才能正常工作。然后我要做的是将连接逻辑重构为它自己的异步方法。然后你可以所有这些都来自handler.addClientSync
之前的中间件,但这仍然会将其与Invoke
方法中的每个HTTP/TCP请求相耦合。我仍然需要在每个Invoke()
调用中放置一点得到计算的if()…
。if语句可以在新连接方法中