Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

220
Views
¿Cómo creo de forma segura una conexión de cliente SignalR compartida?

Lo admito, probablemente ni siquiera sea una pregunta específica de SignalR, sino más bien una pregunta de "hacerlo de la manera correcta". Por lo general, en C#, podríamos crear un singleton de algo compartido haciéndolo estático y luego usando un lock a su alrededor para que solo un subproceso pueda crear el objeto compartido. Usando el cliente Javascript SignalR, me gustaría hacer lo mismo, sin tener que preocuparme por si dos componentes quieren usar una conexión o no. Mi solución es esta, pero aún da como resultado una condición de carrera en la que dos componentes web obtienen cada uno su propia instancia de conexión:

 export class MessagingService {
 private static service: MessagingService;

 static async GetService(): Promise<MessagingService> {
 if (!this.service) {
 let service = new MessagingService();
 await service.start();
 this.service = service;
 }
 return this.service;
 }

 connection;

 async start() {
 this.connection = new signalR.HubConnectionBuilder().withUrl("/MyHub").withAutomaticReconnect().build();

 await this.connection.start();
 }
}

Ingenuamente, no esperaría que dos componentes web en la página llamaran await MessagingService.GetService() desde sus métodos async connectedCallback() , para que cada uno termine con su propia instancia de MessagingService y, por lo tanto, conexión, pero eso es exactamente lo que sucede.

Innumerables otras preguntas en Internet sugieren que el bloqueo no es lo que necesito aquí, sino que lo estoy haciendo mal. ¿Cómo puedo asegurarme de que solo se crea una de estas conexiones?

almost 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Mi cerebro C# no estaba pensando en promesas. Estaba fingiendo un bloqueo en el miembro de la instancia estática, que no se asignó hasta que se creó e inició la conexión SignalR, por lo que no sorprende que diferentes componentes llegaran al mismo tiempo y no encontraran una instancia lista. Si bien pude reordenar el código para asignarlo de inmediato, los segundos en llegar a la llamada descubrieron que la conexión estaba allí, pero no había terminado de abrirse, por lo que falló la invoke de llamadas en su contra.

El truco consistía en verificar primero la promesa y luego esperar a que se completara. El código resultante fue este:

 export class MessagingService {
 private static service: MessagingService;
 private static promise: Promise<void>;

 static async GetService(): Promise<MessagingService> {
 if (!this.promise) {
 const service = new MessagingService();
 this.promise = service.start();
 this.service = service;
 }
 await Promise.all([this.promise]);
 return this.service;
 }

 connection: any;

 private async start() {
 this.connection = new signalR.HubConnectionBuilder().withUrl("/MyHub").withAutomaticReconnect().build();
 await this.connection.start();
 }
}

La promesa estática se asignó al método start() , que es esencialmente la parte que inicia la conexión. Antes de devolver la instancia de servicio, await Promise.all([this.promise]) para asegurarme de que esté listo. Esto parece resolver la condición de carrera, pero no estoy convencido de que sea posible que dos personas que llaman aterricen en la primera línea del método GetService() y aún así encuentren que no hay promesa.

almost 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!