问题
I'm using ADO.NET dataservices in a Silverlight application and since the silverlight libraries don't support the ToList() call on the IQueryable I thought it might be possible to create an extension method around this called SilverlightToList(). So in this method I'm calling the BeginExecute method on my context as shown below:
var result = context.BeginExecute<T>(currentRequestUri,null,context);
result.AsyncWaitHandle.WaitOne();
return context.EndExecute<T>(result).ToList();
The problem is that when I call the WaitOne() method this results in a deadlock. Is this a limitation of ADO.NET dataservices in Silverlight? Is there perhaps a workaround for this?
回答1:
I have managed to defeat ( :P ) the async monster in silverlight like so:
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..
});
The basic ideea is to spawn a waiter thread (the last block) which would have references to the wait objects. DON'T put your WaitAll call in the caller method / thread because this will result in a deadlock as others mentioned earlier on this site or other sites.
The deadlock occurs because the threads are not starting until the method ends and the method does not end because the WaitAll call waits for the child threads to end.
Not in my case above however because the WaitAll is on ANOTHER thread.
PS : Instead of the // do your thing line place code that uses the r1 and r2 captured references which will hold the data or null if that result failed.
回答2:
I've since found this post on the MSDN forum which says that any managed->UnManaged->Managed marshalling happens on the UI thread which explains why the WaitOne method call is hanging...
回答3:
Silverlight probably isn't going to like synchronous anything, because it's intended to run in the browser, and it only can have one thread to play with - and it has to share that. And the only thread available for the host is the one provided by the browser.
回答4:
All service calls in Silverlight must be asynchronous. So you have to define a callback to get the result - like this:
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
}
Here's a good reference at MSDN: http://msdn.microsoft.com/en-us/library/cc838191(VS.95).aspx
来源:https://stackoverflow.com/questions/351644/synchronous-ado-net-dataservices-calls-in-silverlight