Tengo un método en el que me gustaría ejecutar tres consultas en paralelo. Estoy tratando de usar la biblioteca Task Parallel para hacerlo como se muestra:
internal static async Task<RequestAppointmentDBMasterObject> GetDAMasterObject(string facility, string sites, string state) { RequestAppointmentDBMasterObject mo = new RequestAppointmentDBMasterObject(); string querySites = query1; string queryPractitioners = query2; string queryExistingAppts = query3; using (IDbConnection db = new OdbcConnection(connectionString)) { await Task.Run(() => { Parallel.Invoke( () => { mo.SiteList = db.Query<Sites>(querySites).ToList(); }, () => { mo.PractitionerList = db.Query<Practitioners>(queryPractitioners).ToList(); }, () => { mo.ExistingAppointments = db.Query<AvailResponseObject>(queryExistingAppts).ToList(); } ); }); } return mo; }Luego, en otra clase estoy llamando a este método para configurar el objeto con el que voy a trabajar como se muestra a continuación:
RequestAppointmentDBMasterObject mo = DataAccess.GetDAMasterObject(facility, site, state).Result;El problema es que nunca obtengo un resultado cuando llamo a la API. Una vez que cambio todo de nuevo para no usar las bibliotecas Task y Parallel. todo funciona bien También probé este mismo código en una aplicación de consola y recuperé los datos. No estoy seguro de por qué podría faltar el código para poder usarlo en mi API. Gracias de antemano.
Esto es enormemente más complejo de lo necesario. Tener capas de tareas que envuelven a otras generalmente no es el enfoque correcto.
Sería mejor realizar las tres consultas como operaciones asíncronas (es decir, devuelven Task<T> y luego las esperan en paralelo:
var t1 = db.QueryAsync(...); var t2 = db.QueryAsync(...); var t3 = db.QueryAsync(...); await Task.WhenAll(t1, t2, t3);Esto depende de que la conexión de la base de datos admita múltiples conexiones simultáneas (esto generalmente no es cierto).
Utilice t1.Result etc. para obtener los valores devueltos.
Como se indica en los comentarios, no desea utilizar Parallel en absoluto. En su lugar, utilice la simultaneidad asíncrona ( await Task.WhenAll ).
Sin embargo, la mayoría de los proveedores de bases de datos no permiten varias solicitudes simultáneas a través de la misma conexión de base de datos. Por lo tanto, probablemente necesitará tener tres conexiones de base de datos diferentes para ejecutar tres consultas al mismo tiempo.
internal static async Task<RequestAppointmentDBMasterObject> GetDAMasterObject(string facility, string sites, string state) { RequestAppointmentDBMasterObject mo = new RequestAppointmentDBMasterObject(); string querySites = query1; string queryPractitioners = query2; string queryExistingAppts = query3; using (IDbConnection db1 = new OdbcConnection(connectionString)) using (IDbConnection db2 = new OdbcConnection(connectionString)) using (IDbConnection db3 = new OdbcConnection(connectionString)) { var task1 = db1.Query<Sites>(querySites).ToListAsync(); var task2 = db2.Query<Practitioners>(queryPractitioners).ToListAsync(); var task3 = db3.Query<AvailResponseObject>(queryExistingAppts).ToListAsync(); await Task.WhenAll(task1, task2, task3); mo.SiteList = await task1; mo.PractitionerList = await task2; mo.ExistingAppointments = await task3; } return mo; }Es posible hacer múltiples consultas simultáneas como esta, pero generalmente es mejor hacer una sola consulta que recupere todo de una vez. De esa manera, solo necesita una única conexión de base de datos, y todos los resultados de la consulta son consistentes entre sí.