• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

259
Views
Cómo manejar un interbloqueo en código de terceros

Tenemos un método de terceros, Foo , que a veces se bloquea por razones desconocidas.

Estamos ejecutando un servidor tcp de subproceso único y llamamos a este método cada 30 segundos para verificar que el sistema externo esté disponible.

Para mitigar el problema con el punto muerto en el código de terceros, colocamos la llamada de ping en una Task.Run para que el servidor no se bloquee.

Me gusta

 async Task<bool> WrappedFoo() { var timeout = 10000; var task = Task.Run(() => ThirdPartyCode.Foo()); var delay = Task.Delay(timeout); if (delay == await Task.WhenAny(delay, task )) { return false; } else { return await task ; } }

Pero esto (en nuestra opinión) tiene el potencial de privar a la aplicación de hilos gratuitos. Dado que si una llamada a ThirdPartyCode.Foo interbloquea, el subproceso nunca se recuperará de este interbloqueo y, si esto sucede con la frecuencia suficiente, es posible que nos quedemos sin recursos.

¿Existe un enfoque general sobre cómo se debe manejar el código de terceros que bloquea los puntos muertos?

Un CancellationToken no funcionará porque la API de terceros no proporciona ninguna opción de cancelación.

Actualización: el método en cuestión es de SAPNCO.dll proporcionado por SAP para establecer y probar conexiones rfc a un sistema sap, por lo tanto, el método no es un simple ping de red. Cambié el nombre del método en la pregunta para evitar más malentendidos.

about 3 years ago · Santiago Trujillo
3 answers
Answer question

0

¿Existe un enfoque general sobre cómo se debe manejar el código de terceros que bloquea los puntos muertos?

Sí, pero no es fácil ni sencillo.

El problema con el código que se comporta mal es que no solo puede filtrar recursos (p. ej., subprocesos), sino que también puede conservar indefinidamente recursos importantes (p. ej., algún "control" o "bloqueo" interno).

La única forma de reclamar a la fuerza hilos y otros recursos es finalizar el proceso. El sistema operativo está acostumbrado a limpiar procesos que se comportan mal y es muy bueno en eso. Entonces, la solución aquí es iniciar un proceso secundario para realizar la llamada a la API. Su aplicación principal puede comunicarse con su proceso secundario mediante stdin/stdout redirigidos, y si el proceso secundario alguna vez se agota, la aplicación principal puede finalizarlo y reiniciarlo.

Desafortunadamente, esta es la única forma confiable de cancelar un código que no se puede cancelar.

about 3 years ago · Santiago Trujillo Report

0

Tu código no cancela la operación bloqueada. Use un CancellationTokenSource y pase un token de cancelación a Task.Run en su lugar:

 var cts=new CancellationTokenSource(timeout); try { await Task.Run(() => ThirdPartyCode.Ping(),cts.Token); return true; } catch(TaskCancelledException) { return false; }

Es muy posible que el bloqueo se deba a problemas de red o de DNS, no a un punto muerto real.

Eso todavía desperdicia un hilo esperando que se complete una operación de red. Puede usar el propio Ping.SendPingAsync de .NET para hacer ping de forma asincrónica y especificar un tiempo de espera:

 var ping=new Ping(); var reply=await ping.SendPingAsync(ip,timeout); return reply.Status==IPStatus.Success;

La clase PingReply contiene información mucho más detallada que un simple éxito/fracaso. La propiedad Estado por sí sola diferencia entre problemas de enrutamiento, destinos inalcanzables, tiempos de espera, etc.

about 3 years ago · Santiago Trujillo Report

0

Cancelar una tarea es una operación colaborativa en la que pasa un CancellationToken al método deseado y externamente usa CancellationTokenSource.Cancel :

 public void Caller() { try { CancellationTokenSource cts=new CancellationTokenSource(); Task longRunning= Task.Run(()=>CancellableThirdParty(cts.Token),cts.Token); Thread.Sleep(3000); //or condition /signal cts.Cancel(); }catch(OperationCancelledException ex) { //treat somehow } } public void CancellableThirdParty(CancellationToken token) { while(true) { // token.ThrowIfCancellationRequested() -- if you don't treat the cancellation here if(token.IsCancellationRequested) { // code to treat the cancellation signal //throw new OperationCancelledException($"[Reason]"); } } }

Como puede ver en el código anterior, para cancelar una tarea en curso, el método que se ejecuta dentro de ella debe estar estructurado en torno al indicador CancellationToken.IsCancellationRequested o simplemente al método CancellationToken.ThrowIfCancellationRequested , de modo que la persona que llama simplemente emita CancellationTokenSource.Cancel .

Desafortunadamente, si el código de terceros no está diseñado en torno a CancellationToken (no acepta un parámetro CancellationToken ), entonces no hay mucho que pueda hacer.

about 3 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 Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error