2010-03-01 3 views
3

J'ai un certain nombre de contrôles de grille Janus qui doivent être remplis au démarrage d'une application.WinForms Control.BeginInvoke rappel asynchrone

Je voudrais charger ces grilles sur différents threads pour accélérer le temps de démarrage et le temps qu'il faut pour actualiser ces grilles. Chaque grille est sur un onglet séparé. Idéalement, je voudrais utiliser Control.BeginInvoke sur chaque grille et sur la charge de la grille en complétant les onglets deviendra activé. Je sais qu'avec les délégués, vous pouvez effectuer un rappel asynchrone lors de l'utilisation de BeginInvoke, donc je pourrais activer les onglets dans le rappel asynchrone, cependant en utilisant Control.BeginInvoke, cela n'est pas possible. Y at-il un moyen de faire des rappels asynchrones en utilisant Control.BeginInvoke ou peut-être une meilleure solution?

Jusqu'à présent, j'ai:

public delegate void BindDelegate(IMyGrid grid); 

private IAsyncResult InvokeBind(IMyGrid grid) 
{ 
    return ((Control)grid).BeginInvoke(
    new BindDelegate(DoBind), new object[] { grid } 
); 
} 

private void DoBind(IMyGrid grid) 
{ 
    grid.Bind(); // Expensive operation 
} 

private void RefreshComplete() 
{ 
    IAsyncResult grid1Asynch = InvokeBind(grid1); 
    IAsyncResult grid2Asynch = InvokeBind(grid2); 
    IAsyncResult grid3Asynch = InvokeBind(grid2); 
    IAsyncResult grid4Asynch = InvokeBind(grid3); 
    IAsyncResult grid5Asynch = InvokeBind(grid4); 
    IAsyncResult grid6Asynch = InvokeBind(grid5); 
} 

Maintenant, je pourrais essaimer un thread séparé et continuer de vérifier si les IAsynchResults ont terminé et selon laquelle on effectue je pouvais réactiver le contrôle de l'onglet que la la grille est contenue dans. Y at-il une meilleure façon de le faire?

Répondre

1

Toute manipulation directe d'un Control (instance qui inclut toutes les commandes WinForms standard et d'extension) doit être effectuée sur le thread sur lequel ce contrôle a été créé. L'interface graphique Windows n'est pas thread-safe, en effet chaque fenêtre créée (et la plupart des contrôles en créeront au moins une) a une affinité de thread.

Normalement, Control.BeginInvoke est utilisé par d'autres threads pour effectuer une action sur le thread graphique afin que les propriétés puissent être lues ou définies correctement. Vous pouvez certainement générer des éléments de travail dans le pool de threads pour obtenir des données avec lesquelles vous allez remplir les grilles ultérieurement, mais la configuration et la population réelles des grilles (y compris la liaison de données) doivent être effectuées sur le thread graphique. Si cela prend du temps pour obtenir les données c'est probablement une bonne idée (mais les faire tous ensemble peut être plus lent en raison de la contention à la source de données que tout à la fois) parce que vous pouvez répondre à l'interface graphique.

+0

Peut-être qu'il peut être utile d'utiliser aussi 'SuspendLayout()' et 'ResumeLayout (false)' avant et après le remplissage, afin que la grille ne soit pas peinte avec des états immédiats. – Oliver

Questions connexes