¿Es posible usar Control.BeginInvoke en algo que no sea "fire & forget"? Deseo cambiar la siguiente solicitud para delegar un método de devolución de llamada para que pueda hacer algo cuando se complete cada una de mis llamadas asincrónicas.¿Cómo delego un método AsyncCallback para Control.BeginInvoke? (.NET)
this.BeginInvoke(new RefreshRulesDelegate(RefreshRules), new object[] { ctrl, ctrl.DsRules, ctrl.CptyId });
que sería capaz de hacer esto con una normal de delegate.BeginInvoke por ejemplo
RefreshRulesDelegate del = new RefreshRulesDelegate(RefreshRules);
del.BeginInvoke(ctrl, ctrl.DsRules, ctrl.CptyId, new AsyncCallback(RefreshCompleted), del);
Pero debido a que estoy llamando control .BeginInvoke No puedo hacer esto como llegue a la "operación entre subprocesos no válida" error.
¿Alguien ayuda?
Además de algunas de las respuestas recibidas, aclararé el "por qué". Necesito cargar/actualizar un Control en mi GUI sin bloquear el resto de la aplicación. El control contiene numerosos controles (ruleListCtls) que requieren un conjunto de datos para ser recuperados y pasados a ellos. es decir
public void RefreshAll()
{
foreach (LTRFundingRuleListControl ctrl in ruleListCtls)
{
this.BeginInvoke(new RefreshRulesDelegate(RefreshRules), new object[]{ctrl,ctrl.DsRules, ctrl.CptyId });
}
}
he encontrado que puedo hacer esto si proporcionar un método delegado de devolución de llamada y mover cualquier código que modifica los controles de nuevo en el hilo GUI principal en el que se crearon (para evitar el error de hilo cruzado)
public void RefreshAll()
{
IntPtr handle;
foreach (LTRFundingRuleListControl ctrl in ruleListCtls)
{
handle = ctrl.Handle;
RefreshRulesDsDelegate del = new RefreshRulesDsDelegate(RefreshRulesDs);
del.BeginInvoke(ctrl.DsRules, ctrl.CptyId, handle, out handle, new AsyncCallback(RefreshCompleted), del);
}
}
private void RefreshCompleted(IAsyncResult result)
{
CptyCatRuleDataSet dsRules;
string cptyId;
IntPtr handle;
AsyncResult res = (AsyncResult) result;
// Get the handle of the control to update, and the dataset to update it with
RefreshRulesDsDelegate del = (RefreshRulesDsDelegate) res.AsyncDelegate;
dsRules = del.EndInvoke(out handle,res);
// Update the control on the thread it was created on
this.BeginInvoke(new UpdateControlDatasetDelegate(UpdateControlDataset), new object[] {dsRules, handle});
}
public delegate CptyCatRuleDataSet RefreshRulesDsDelegate(CptyCatRuleDataSet dsRules, string cptyId, IntPtr ctrlId, out IntPtr handle);
private CptyCatRuleDataSet RefreshRulesDs(CptyCatRuleDataSet dsRules, string ruleCptyId, IntPtr ctrlId, out IntPtr handle)
{
try
{
handle = ctrlId;
int catId = ((CptyCatRuleDataSet.PSLTR_RULE_CAT_CPTY_SelRow)dsRules.PSLTR_RULE_CAT_CPTY_Sel.Rows[0]).RULE_CAT_ID;
return ltrCptyRulesService.GetCptyRules(ruleCptyId, catId);
}
catch (Exception ex)
{
throw ex;
}
}
Aquí es lo que delgate al hilo principal de haber recibido la devolución de llamada:
private delegate void UpdateControlDatasetDelegate(CptyCatRuleDataSet dsRules, IntPtr ctrlId);
private void UpdateControlDataset(CptyCatRuleDataSet dsRules, IntPtr ctrlId)
{
IEnumerator en = ruleListCtls.GetEnumerator();
while (en.MoveNext())
{
LTRFundingRuleListControl ctrl = en.Current as LTRFundingRuleListControl;
if (ctrl.Handle == ctrlId)
{
ctrl.DsRules = dsRules;
}
}
}
Esto ahora funciona bien. Sin embargo, el problema principal, aparte de eso, no creo que esto sea particularmente elegante, es el manejo de excepciones. Tal vez esta es otra pregunta, pero si RefreshRulesDs arroja una excepción, entonces mi aplicación falla ya que el error no se borra una copia de seguridad del hilo de la GUI (obviamente) sino como una excepción no controlada. Hasta que pueda atraparlos, tendré que hacer toda esta operación sincrónicamente. ¿Cómo atrapo exitosamente un error y cargo el resto de mis controles? ¿O cómo puedo lograr esta operación asíncrona de otra manera, con el manejo de excepciones adecuado?
El manejo de excepciones es un poco desordenado, pero deberías poder atraparlos rodeando a EndInvoke. BackgroundWorker y Task (Fx 4) lo hacen mejor. –