2013-02-10 5 views
0

Je suis venu avec une idée sur la fausse prise en charge SL WCF pour les appels synchrones.Verrouillage de thread de rappel asynchrone dans Silverlight WCF

Fondamentalement,

private _completed; 
private IList<Customer> _customers; 
public void IList<Customer> GetAllCustomers() 
{ 
    bool completed = false; 
    DataServiceQuery<Customer> myQuery = this.Context.Customers; 
    myQuery.BeginExecute(OnQueryExecuted, myQuery); 

    while (!_completed) 
     System.Threading.Thread.Sleep(67); //tried join also 

    return _customers; 
} 

private void OnQueryExecuted(IAsyncResult result) 
{ 
    var query = result.AsyncState as DataServiceQuery<Customer>; 
    _customers = query.EndExecute(result).ToList(); 
    _isCompleted = true; 
} 

Ce qui se passe est que cette boucles pour toujours.

Je place un point d'arrêt sur la boucle while, je l'éloigne et je reprends l'exécution, et les résultats arrivent dans la milliseconde suivante.

Alors, je pense que le rappel de la requête pour recevoir les résultats obtient en file d'attente au même thread la requête a été invoqué.

SL semble très déterminé à maintenir ce comportement, même si j'Enroulez le myQuery.BeginExecute dans un nouveau thread, j'ai toujours le même comportement.

/* edit: en fait, en y réfléchissant, il met en attente le rappel sur le thread ui, qui attend. C'est aussi la raison pour laquelle nous n'avons pas à Dispatcher.Invoke lorsque nous obtenons les résultats. de toute façon, je peux toujours faire l'ensemble de l'opération (qui nécessite l'attente) dans un fil dédié, puis attendre là, mais cela nécessitera un tas de refactoring, évitant ce qui est le point d'essayer cela. */

Y at-il un moyen de contourner cela?

+0

vous bloquez le thread UI d'une façon ou d'une autre, au lieu de boucler pourquoi ne pas simplement appeler 'Execute'? Cette méthode 'GetAllCustomers' ne sera jamais asynchrone de toute façon dans la forme que vous avez maintenant, alors appelez simplement' Execute' à la place. Je ne comprends pas pourquoi vous essayez d'impliquer dans le deuxième thread au lieu de bloquer un seul thread - il n'y a aucun avantage du tout et il dégrade les performances de l'application. Pourriez-vous élaborer un peu plus? – user1416420

+0

le point est pour qu'il ne soit pas asynchrone. l'appel db est asynchrone à cause du 'myQuery.BeginExecute'. de toute façon, si j'appelle 'Execute', Silverlight m'informe brusquement qu'il ne supporte pas l'interrogation synchrone. –

+0

oh, je vois, je ne savais pas cela, laissez-moi regarder autour .. – user1416420

Répondre

1

La raison pour laquelle cela se bloque est que la méthode EndExecute est associée au thread d'interface utilisateur, mais vous bloquez le thread d'interface utilisateur avec votre appel Sleep. Peu importe la technique que vous utilisez pour bloquer le thread, tout ce que vous faites va provoquer un blocage étant donné que la méthode est appelée dans un thread d'interface utilisateur. Lors du développement dans un environnement SIlverlight, vous devez pouvoir programmer de manière asynchrone, plutôt que d'utiliser des méthodes synchrones. Si vous utilisez C# 5.0, vous pouvez utiliser la fonctionnalité async/await, qui vous permet d'écrire du code asynchrone apparaît synchrone, mais il sera compilé en appels asynchrones qui utilisent des rappels/continuations, ce qui est ce que vous devez faire si vous n'avez pas encore mis à niveau vers cette version.

+0

Donc, s'ils ont permis de bloquer le thread UI dans les applications Win, pourquoi pas dans SL? Après tout, vous allez tester, et si quelque chose se bloque, vous le ferez asynchrone. Ces choses reviennent en moins de 100 millisecondes de toute façon. Il ne s'agit pas simplement de tout mettre en continuité, maintenant je dois faire une vérification de la concurrence pour un tas de choses. Si l'utilisateur a cliqué sur rafraîchir une liste de données, je devrais désactiver le chargement des éléments jusqu'à ce qu'il revienne .. etc. 'async/await' est super, mais ne résout pas ce problème. –

+0

Et qu'est-ce que je gagne? Zéro! Je peux aussi limiter mon attente à 133ms, déclarer que le serveur ne répond pas et montrer une erreur à l'utilisateur .. Pour les petits allers-retours. Les plus grands que je ferais, comme toute personne sensée, async. Mais, d'accord, laissons tomber le passé, et maintenant faisons tous nos voyages asynchrones partout et toujours. –

+0

@ h.alex Le fait est que le blocage du thread d'interface utilisateur gèle l'ensemble de l'application. Vous empêchez l'exécution des événements de peinture, vous empêchez l'utilisateur de déplacer le navigateur, vous empêchez ceux-ci de naviguer ou de changer d'onglet. C'est extrêmement préjudiciable à l'expérience utilisateur. – Servy

Questions connexes