Chiamate di servizi di dati ADO.NET sincroni in Silverlight
-
20-08-2019 - |
Domanda
Sto usando i dataservices ADO.NET in un'applicazione Silverlight e poiché le librerie silverlight non supportano la chiamata ToList () su IQueryable, ho pensato che fosse possibile creare un metodo di estensione attorno a questo chiamato SilverlightToList (). Quindi in questo metodo sto chiamando il metodo BeginExecute sul mio contesto come mostrato di seguito:
var result = context.BeginExecute<T>(currentRequestUri,null,context);
result.AsyncWaitHandle.WaitOne();
return context.EndExecute<T>(result).ToList();
Il problema è che quando chiamo il metodo WaitOne () questo provoca un deadlock. È una limitazione dei servizi dati ADO.NET in Silverlight? C'è forse una soluzione alternativa per questo?
Soluzione 2
Da allora ho trovato questo post sul forum MSDN che dice che qualsiasi gestito - > UnManaged - > Il marshalling gestito avviene sul thread dell'interfaccia utente, il che spiega perché la chiamata del metodo WaitOne è in sospeso ...
Altri suggerimenti
Sono riuscito a sconfiggere (: P) il mostro asincrono in Silverlight in questo modo:
var ctx = new ModelEntities(new Uri("http://localhost:2115/Data.svc"));
ManualResetEvent m1 = new ManualResetEvent(false);
ManualResetEvent m2 = new ManualResetEvent(false);
var q1 = (DataServiceQuery<Department>)(from e in ctx.Department select e);
var q2 = (DataServiceQuery<Person>)(from e in ctx.Person select e);
Department[] r1 = null;
Person[] r2 = null;
q1.BeginExecute(r =>
{
try { r1 = q1.EndExecute(r).ToArray(); }
finally { m1.Set(); }
}, null);
q2.BeginExecute(r =>
{
try { r2 = q2.EndExecute(r).ToArray(); }
finally { m2.Set(); }
}, null);
ThreadPool.QueueUserWorkItem((o) =>
{
WaitHandle.WaitAll(new WaitHandle[] { m1, m2 });
// do your thing..
});
L'ideea di base è generare un thread del cameriere (l'ultimo blocco) che avrebbe riferimenti agli oggetti wait. NON inserire la chiamata WaitAll nel metodo / thread del chiamante perché ciò comporterà un deadlock come altri precedentemente menzionati su questo sito o altri siti.
Il deadlock si verifica perché i thread non si avviano fino alla fine del metodo e il metodo non termina perché la chiamata WaitAll attende la fine dei thread figlio.
Non nel mio caso sopra però perché WaitAll è su UN ALTRO thread.
PS: Invece del // fai il tuo codice di posizione della linea di cose che utilizza i riferimenti acquisiti r1 e r2 che conterranno i dati o null se quel risultato non è riuscito.
Probabilmente a Silverlight non piacerà nulla di sincrono, perché è progettato per essere eseguito nel browser e può avere solo un thread con cui giocare - e deve condividerlo. E l'unico thread disponibile per l'host è quello fornito dal browser.
Tutte le chiamate di servizio in Silverlight devono essere asincrone. Quindi devi definire un callback per ottenere il risultato - in questo modo:
context.BeginExecute<T>(currentRequestUri, resultCallback, context);
private void resultCallback(IAsyncResult asyncResult)
{
DataServiceContext context = asyncResult.AsyncState as DataServiceContext;
var result = context.EndExecute<T>(asyncResult);
// Do whatever you need with the result here
}
Ecco un buon riferimento a MSDN: http://msdn.microsoft.com/en- us / library / cc838191 (VS.95) aspx