Bonjour à tous,
Je développe un application WinForm en C# 2.0.
Le problème qui se pose me semble réellement "basique":
J'utilise un BackGroundWorker pour récupérer les données de ma DataLayer (ex: liste de contrats). Grace au BgWorker, mon interface ne "freeze" pas et reste réactive. Le problème survient lorsque je procède au Databind de ma collection d'objets à ma UI (que ce soit un DataGridView, ListBox, ComboBox, ListView, ...).
J'utilise le code suivant (je place bien le DisplayMember et ValueMember avant le DataSource, ce qui est sensé améliorer la rapidité du DataBind):
grid.DisplayMember = "UCN";
grid.ValueMember = "ContractID";
grid.DataSource = datasource;
Le vrai problème reste que j'ai généralement des DataSources qui contiennent de ~500 à 50.000 records. Le Databind fait alors "freezer" toute mon interface.
J'ai trouvé de la documentation à propos de Invoke et BeginInvoke qui semblent être la piste à suivre (j'ai suivi l'exemple suivant, voir bout de code à la fin de l'article: http://www.codeproject.com/KB/cs/Asy...nvocation.aspx) mais cela n'a pas changé le fait que mon interface freeze pendant quelques secondes.
Je m'étonne de ne pas trouver de solution évidente à mon problème, peut-être n'ai-je pas recherché sur les bons termes dans Google,...?
Que me conseillez-vous pour arriver à obtenir une interface "réactive", j'aimerais afficher un progressBar pendant que mon composant UI soit Databindé (je le fais déjà pour des traitements non UI, ca marche très bien, le problème se pose dès qu'il y a du Databinding).
Auriez-vous un exemple concret, ou une explication peut-être du pourquoi mon test ne marche pas...?
J'espère que mon explication est suffisament claire.
Merci d'avance
Mike
N.B.: Je me suis dit qu'avec un exemple de code ce serait plus clair:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 public interface ICommand { void Execute(); } public class GetContractListCommand : ICommand { private GetContractListDelegate m_invokeMe; private ListBox m_box; private int m_intCustmerId; // notice that the delegate is private, // only the command can use it. private delegate TList<BLL.Contract> GetContractListDelegate(); public GetContractListCommand(TList<BLL.Contract> contracts, ListBox listBox) { m_box = listBox; // setup the delegate to call m_invokeMe = new GetContractListDelegate(DAL.DataRepository.ContractProvider.GetAll); } public void Execute() { // call the method on the thread pool m_invokeMe.BeginInvoke( this.CallBack, // callback! null); } private void CallBack(IAsyncResult ar) { // get the Collection of Contracts as output TList<BLL.Contract> datasource = m_invokeMe.EndInvoke(ar); // update the ListBox a thread safe fasion! MethodInvoker updateListBox = delegate { m_box.DisplayMember = "UCN"; m_box.ValueMember = "ContractID"; m_box.DataSource = datasource; }; if (m_box.InvokeRequired) m_box.Invoke(updateListBox); else updateListBox(); } } partial class PanelContracts : UserControl { private ICommand m_GetContractListCommand; protected WorkspaceManager m_WorkspaceSubject; protected TList<BLL.Contract> m_Contracts; public PanelContracts(WorkspaceManager workspace) { InitializeComponent(); Load(); } private void Load() { // create a command that has all the tools to update the grid m_GetContractListCommand = new GetContractListCommand( m_Contracts, boxContracts); // call the command in a non blocking mode. m_GetContractListCommand.Execute(); } }
Partager