Bonjour,
j'essaie d'implémenter du développement asynchrone dans mon appli silverlight et après avoir lu la msdn je dois dire que j'ai plus de nœuds au cerveau qu'avant ... donc je viens vous demander conseil
Dans le principe je veux effectuer ceci :
J'ai des objets distribué via un service WCF mais mon appli est assez persistante et donc certaines parties de l'application peuvent avoir à nouveau besoin de ces objets donc pour éviter de les télécharger a nouveau j'ai mis une couche de synchronisation (ou plus simplement cache) devant mon service et j'appel cette couche au lieu d'appeler le service.
Sauf que comme le service est asynchrone je doit faire cette couche de manière asynchrone aussi et la je galère pas mal ...
En gros niveau code métier c'est très simple : si l'objet est dans une liste je lève un événement "completed" qui contient l'objet, si il est pas la je fais appel au service qui va lever l'événement completed du service, que j'utilise pour lever mon événement completed.
Si j'ai bien tout compris il me faut 3 méthodes (et un événement) :
methodAsync : appelé par le client et fait un BeginInvoke sur un objet AsyncCallback créé a partir de la méthode métier.
method : la méthode métier (récupère l'objet dans le cache ou appel le service) qui prend un argument un IAsyncResult dans lequel je met une variable input (long ID). A priori exécute dans un autre thread
methodCallback : la méthode exécute dans le thread principal (je crois) qui va s'occuper de lever l'événement indiquant que c'est fini contenant l'objet UNIQUEMENT si l'objet était bien présent dans le cache.
Mon problème vient du fait que je passe l'objet IAsyncResult ente la méthode et le callback (c'est donc la seul "source d information"), mais un IAsyncResult est read only donc je ne peux pas y mettre mon objet dedans.
En gros ma question est celle ci : Comment "passer" de la donné dans le callback ? Le but est de faire une archi proche des clients de service WCF
Après j'aurai pu lever l'événement dans la méthode principal mais je pense qu'elle n'aurai pas été dans le bon thread.
Comme du code vaut mieux qu'un long discours en voici un peu :
Voila c'est un peu long désolé
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 public abstract class SynchronizationManager<T> where T : IEntityUpdatable<T> { protected IGameController Controller; protected Dictionary<long,T> Entities; public void GetAsync(long id) { AsyncCallback async = new AsyncCallback(Get); async.BeginInvoke(new AsyncResult { AsyncState = id }, new AsyncCallback(GetEnded), id + 1); } private void Get(IAsyncResult ar) { long id = (long)ar.AsyncState; lock (Entities) { if (Entities.ContainsKey(id)) { //FAIL //ar.AsyncState = Entities[id]; //ar.IsCompleted = true; } else { //FAIL //ar.IsCompleted = false; ServiceGet(id); } } } private void GetEnded(IAsyncResult ar) { if (ar.IsCompleted) OnGetCompleted((T)ar.AsyncState); } public event EventHandler<T> GetCompleted; protected void OnGetCompleted(T obj) { if (GetCompleted != null) GetCompleted(this, obj); } public T Update(T obj) { if (Entities.ContainsKey(obj.ID)) { if (Entities[obj.ID].LocalUpdateDate < obj.LocalUpdateDate) { Entities[obj.ID].Update(obj); } } else Entities.Add(obj.ID, obj); } public abstract T ServiceGet(long id);
Si vous avez une solution plus efficace pour faire du cache sur les service je suis pas contre mais si je pouvais tout de même avoir des explications sur la programmation asynchrone ca serai top
merci d'avance![]()
Partager