Вопрос

Я использую службы данных ADO.NET в приложении Silverlight, и поскольку библиотеки Silverlight не поддерживают вызов ToList() в IQueryable, я подумал, что можно было бы создать для этого метод расширения под названием SilverlightToList().Итак, в этом методе я вызываю метод BeginExecute в своем контексте, как показано ниже:

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

Проблема в том, что когда я вызываю метод WaitOne(), это приводит к взаимоблокировке.Является ли это ограничением служб данных ADO.NET в Silverlight?Возможно, есть обходной путь для этого?

Это было полезно?

Решение 2

с тех пор я нашел эта почта на форуме MSDN, где говорится, что любой управляемый->Неуправляемый->Управляемый маршалинг происходит в потоке пользовательского интерфейса, что объясняет, почему вызов метода WaitOne зависает...

Другие советы

Мне удалось победить (:P) асинхронного монстра в silverlight вот так:

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:Вместо строки // do yourthing разместите код, который использует захваченные ссылки r1 и r2, которые будут содержать данные или ноль, если этот результат не удался.

Silverlight, вероятно, не понравится ничего синхронного, потому что он предназначен для запуска в браузере и может иметь только один поток для работы - и он должен делиться им.И единственный поток, доступный хосту, — это поток, предоставляемый браузером.

Все вызовы служб в 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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top