sincrónico sincronico sincronicas sincronica que programacion entre diferencias comunicacion asincrono asincronico asincronica aprendizaje c# asp.net asynchronous task-parallel-library async-await

c# - sincronico - Llamando al método asincrónico sincrónicamente



sincronicas (5)

Necesito llamar a este método desde un método sincrónico.

Es posible con GenerateCodeAsync().Result o GenerateCodeAsync().Wait() , como sugiere la otra respuesta. Esto bloquearía el hilo actual hasta que se complete GenerateCodeAsync .

Sin embargo, su pregunta está etiquetada con asp.net , y también dejó el comentario:

Esperaba una solución más simple, pensando que asp.net manejó esto mucho más fácil que escribir tantas líneas de código

Mi punto es que no deberías estar bloqueando un método asincrónico en ASP.NET. Esto reducirá la escalabilidad de su aplicación web y puede crear un punto muerto (cuando se await una continuación dentro de GenerateCodeAsync en AspNetSynchronizationContext ). El uso de Task.Run(...).Result de descargar algo a un subproceso del grupo y luego bloquear afectará aún más la escalabilidad, ya que incurre en +1 subproceso más para procesar una solicitud HTTP determinada.

ASP.NET tiene soporte integrado para métodos asincrónicos, ya sea a través de controladores asíncronos (en ASP.NET MVC y API web) o directamente a través de AsyncManager y PageAsyncTask en ASP.NET clásico. Deberías usarlo Para más detalles, verifique esta respuesta .

Tengo un método async :

public async Task<string> GenerateCodeAsync() { string code = await GenerateCodeService.GenerateCodeAsync(); return code; }

Necesito llamar a este método desde un método sincrónico.

¿Cómo puedo hacer esto sin tener que duplicar el método GenerateCodeAsync para que esto funcione sincrónicamente?

Actualizar

Sin embargo, no se encontró una solución razonable.

Sin embargo, veo que HttpClient ya implementa este patrón

using (HttpClient client = new HttpClient()) { // async HttpResponseMessage responseAsync = await client.GetAsync(url); // sync HttpResponseMessage responseSync = client.GetAsync(url).Result; }


Debe obtener el awaiter ( GetAwaiter() ) y finalizar la espera para completar la tarea asincrónica ( GetResult() ).

string code = GenerateCodeAsync().GetAwaiter().GetResult();


Debería poder hacer esto usando delegados, expresión lambda

private void button2_Click(object sender, EventArgs e) { label1.Text = "waiting...."; Task<string> sCode = Task.Run(async () => { string msg =await GenerateCodeAsync(); return msg; }); label1.Text += sCode.Result; } private Task<string> GenerateCodeAsync() { return Task.Run<string>(() => GenerateCode()); } private string GenerateCode() { Thread.Sleep(2000); return "I m back" ; }


Microsoft Identity tiene métodos de extensión que llaman a los métodos asincrónicos sincrónicamente. Por ejemplo, hay un método GenerateUserIdentityAsync () e igual CreateIdentity ()

Si miras UserManagerExtensions.CreateIdentity () se verá así:

public static ClaimsIdentity CreateIdentity<TUser, TKey>(this UserManager<TUser, TKey> manager, TUser user, string authenticationType) where TKey : IEquatable<TKey> where TUser : class, IUser<TKey> { if (manager == null) { throw new ArgumentNullException("manager"); } return AsyncHelper.RunSync(() => manager.CreateIdentityAsync(user, authenticationType)); }

Ahora veamos qué hace AsyncHelper.RunSync

public static TResult RunSync<TResult>(Func<Task<TResult>> func) { var cultureUi = CultureInfo.CurrentUICulture; var culture = CultureInfo.CurrentCulture; return _myTaskFactory.StartNew(() => { Thread.CurrentThread.CurrentCulture = culture; Thread.CurrentThread.CurrentUICulture = cultureUi; return func(); }).Unwrap().GetAwaiter().GetResult(); }

Entonces, este es su contenedor para el método asíncrono. Y, por favor, no lea los datos de los resultados: potencialmente bloqueará su código en ASP.

Hay otra forma, lo cual es sospechoso para mí, pero también puedes considerarlo

Result r = null; YourAsyncMethod() .ContinueWith(t => { r = t.Result; }) .Wait();


Puede acceder a la propiedad Result de la tarea, lo que hará que su hilo se bloquee hasta que el resultado esté disponible:

string code = GenerateCodeAsync().Result;

Nota: En algunos casos, esto puede llevar a un interbloqueo: su llamada a Result bloquea el hilo principal, impidiendo así que se ejecute el resto del código asincrónico. Tiene las siguientes opciones para asegurarse de que esto no suceda: