Synchronous ADO.NET dataservices calls in Silverlight

这一生的挚爱 提交于 2019-12-06 07:35:41

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.

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...

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.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!