2008-12-09 2 views
2

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

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

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

+0

Хороший вопрос, общая проблема в Silverlight – 2009-10-08 08:28:46

ответ

1

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

1

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

+0

Имеет ли не только один поток, чтобы иметь возможность вызывать элементы синхронно? – ChrisHDog 2008-12-09 02:55:07

+0

Нет, это означает, что этого не нужно, потому что это заморозит все остальное, что происходит в браузере, на всех вкладках. – dkretz 2008-12-09 03:11:40

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

3

мне удалось победить (: 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.. 
}); 

Основная ideea это породит официант нить (последний блок), которая будет иметь ссылки на объекты ожидания. НЕ помещайте свой вызов WaitAll в метод/поток вызывающего, потому что это приведет к тупиковой ситуации, как другие, упомянутые ранее на этом сайте или на других сайтах.

Тупик возникает из-за того, что потоки не начинаются до тех пор, пока метод не завершится, и метод не завершится, потому что вызов WaitAll ждет завершения дочерних потоков.

Не в моем случае выше, однако, поскольку WaitAll находится в ДРУГОЙ нить.

PS: Вместо // введите код объекта, который использует обратные ссылки r1 и r2, которые будут содержать данные или null, если этот результат не удался.

Смежные вопросы