2

Silverlight アプリケーションで ADO.NET データサービスを使用していますが、Silverlight ライブラリは IQueryable での ToList() 呼び出しをサポートしていないため、SilverlightToList() という拡張メソッドを作成できるのではないかと考えました。したがって、このメソッドでは、以下に示すように、コンテキストで BeginExecute メソッドを呼び出しています。

            var result = context.BeginExecute<T>(currentRequestUri,null,context);
            result.AsyncWaitHandle.WaitOne();
            return context.EndExecute<T>(result).ToList();

問題は、WaitOne() メソッドを呼び出すと、デッドロックが発生することです。これは Silverlight の ADO.NET データサービスの制限ですか? おそらくこれに対する回避策はありますか?

4

4 に答える 4

3

私はなんとか(:P)銀色の光の中で非同期モンスターを次のように倒すことができました:

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..
});

基本的な考え方は、待機オブジェクトへの参照を持つウェイタースレッド(最後のブロック)を生成することです。このサイトまたは他のサイトで前述したように、デッドロックが発生するため、WaitAll呼び出しを呼び出し元のメソッド/スレッドに入れないでください。

デッドロックが発生するのは、メソッドが終了するまでスレッドが開始されず、WaitAll呼び出しが子スレッドの終了を待機するためにメソッドが終了しないためです。

ただし、上記の私の場合は、WaitAllが別のスレッド上にあるためです。

PS://代わりに、データを保持するr1およびr2でキャプチャされた参照を使用するコードを配置し、その結果が失敗した場合はnullを配置します。

于 2009-10-08T08:23:28.503 に答える
1

Silverlight はおそらく同期を好まないでしょう。なぜなら、Silverlight はブラウザーで実行することを意図しており、再生できるスレッドは 1 つだけであり、それを共有する必要があるからです。また、ホストで使用できる唯一のスレッドは、ブラウザーによって提供されるスレッドです。

于 2008-12-09T02:53:23.630 に答える
1

それ以来、MSDN フォーラムでこの投稿を見つけました。これは、WaitOne メソッド呼び出しがハングしている理由を説明する UI スレッドでマネージド -> UnManaged -> マネージド マーシャリングが発生することを示しています...

于 2008-12-09T03:09:32.490 に答える
1

Silverlight のすべてのサービス呼び出しは非同期である必要があります。結果を取得するには、次のようにコールバックを定義する必要があります。

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
}

MSDN の参考資料は次のとおりです。http://msdn.microsoft.com/en-us/library/cc838191(VS.95).aspx

于 2008-12-09T04:51:12.033 に答える