method - generate documentation c#
La mejor manera de usar el.tt 4.5 HttpClient de forma sÃncrona (3)
@Noseratio: por supuesto, me preocupan los puntos muertos :-)
Solo te preocuparían los puntos muertos si estás en un hilo con contexto de sincronización .
Normalmente, ese sería el subproceso principal de una aplicación de UI (lado del cliente) o el subproceso ASP.NET aleatorio que procesa una solicitud HTTP (lado del servidor). En cualquier caso, no deberías bloquearlo.
La respuesta aceptada podría ayudar a mitigar el interbloqueo, pero bloquear de esta manera aún perjudicaría la experiencia del usuario final de su aplicación de UI (la UI se congelaría), o la escalabilidad de la aplicación del lado del servidor (un hilo perdido con el bloqueo, mientras que podría serlo). atendiendo otra petición). Simplemente no bloquee y use async/await
hasta el final.
Usted mencionó "en lo profundo de un servidor" pero no proporcionó detalles sobre qué tipo de aplicación del lado del servidor es esa. La mayoría de los marcos del lado del servidor modernos tienen una buena plomería para async/await
, por lo que no debería ser un problema abrazarlo.
Actualizado para abordar el comentario:
Todavía no me gusta el hecho de que el mismo código escrito en diferentes lugares se bloquee. Espero que la llamada de espera en un entorno propenso a interbloqueos se lance
Este no es particularmente un problema de async/await
sino que es el concepto de contexto de sincronización en general, cuando se usa con código de bloqueo. Aquí está el punto muerto en pocas palabras:
private void Form1_Load(object sender, EventArgs e)
{
var mre = new System.Threading.ManualResetEvent(initialState: false);
System.Threading.SynchronizationContext.Current.Post(_ =>
mre.Set(), null);
mre.WaitOne();
MessageBox.Show("We never get here");
}
En teoría, podría ser posible tratar de mitigar los puntos muertos potenciales dentro de SynchronizationContext.Post
, por ejemplo, verificando Thread.ThreadState == System.Threading.ThreadState.WaitSleepJoin
. Sin embargo, eso no sería una solución 100% confiable.
Me gusta la nueva clase System.Net.Http.HttpClient. Tiene una API simple y agradable, no produce errores normales. Pero solo es asíncrono.
Necesito un código que vaya (en lo profundo de un servidor)
foo();
bar();
// compute stuff
var x = GetThingFromOtherServerViaHttp();
// compute more stuff
wiz(x);
Código síncrono secuencial clásico. Vi varias preguntas de SO que eran similares, pero en realidad nunca terminaron diciendo "haz esto". Miré
client.PostAsync.Wait()
el mundo grita "no hagas esto". Qué tal si:
client.PostAsync.Result()
¿No es esto simplemente esperar disfrazado?
Al final terminé pasando una devolución de llamada lambda que procesó el resultado y luego desperté el hilo de llamada que estaba esperando explícitamente en un EventWaitHandle. Mucha fontanería. ¿Hay algo un poco más simple o shoul? Simplemente vuelvo a usar los antiguos clientes http
EDITAR: Después de leer más, sospecho que este código tiene los mismos problemas que Espera y Resultado, es simplemente un interbloqueo más largo
EDITAR: Hace poco MS PM me confirmó que hay un mandato ''cualquier API que pueda tomar> X ms (olvidé X) debe ser asíncrona'', muchos PM interpretan esto como ''solo asíncrono'' (no está claro si esto es lo que se pretende). De ahí que la base de datos del documento sea solo asíncrona.
Controversialmente voy a decir para System.Net.Http.HttpClient
que probablemente solo puedes usar .Result
Microsoft debería haber seguido sus propios consejos y haber usado .ConfigureAwait(false)
hasta el final de esa biblioteca. La fuente de referencia implica esto:
https://github.com/dotnet/corefx/blob/master/src/System.Net.Http/src/System/Net/Http/HttpClient.cs
¿Por qué correr el riesgo? Porque debería ser un poco más liviano que Task.Run(() => Client.PostAsync()).Result
.
No confiaría en muchas (¿alguna?) Otras bibliotecas para que se codifiquen de forma segura y espero ver si alguien discute mi respuesta o, mejor aún, demuestra que estoy equivocado.
De http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx :
return Task.Run(() => Client.PostAsync()).Result;