Хотя LINQ действительно не имеет этого сам по себе, сам фреймворк ... Вы можете легко свернуть собственный асинхронный исполнитель запросов в 30 строк или так ... На самом деле, я просто бросил это вместе для вас:)
EDIT: Благодаря написанию этого, я обнаружил, почему они не реализовали его. Он не может обрабатывать анонимные типы, поскольку они локализованы локально. Таким образом, у вас нет способа определить вашу функцию обратного вызова. Это довольно важная вещь, поскольку многие элементы linq to sql создают их в предложении select. Любые из приведенных ниже предложений страдают той же судьбой, поэтому я считаю, что этот самый простой в использовании!
EDIT: Единственное решение - не использовать анонимные типы. Вы можете объявить обратный вызов, просто принимая IEnumerable (без аргументов типа), и используйте отражение для доступа к полям (ICK !!). Другой способ - объявить обратный вызов как «динамический» ... о ... подождите ... Это еще не все. :) Это еще один достойный пример того, как можно использовать динамику. Некоторые могут называть это злоупотреблением.
Бросьте это в вашей библиотеке утилит:
public static class AsynchronousQueryExecutor
{
public static void Call<T>(IEnumerable<T> query, Action<IEnumerable<T>> callback, Action<Exception> errorCallback)
{
Func<IEnumerable<T>, IEnumerable<T>> func =
new Func<IEnumerable<T>, IEnumerable<T>>(InnerEnumerate<T>);
IEnumerable<T> result = null;
IAsyncResult ar = func.BeginInvoke(
query,
new AsyncCallback(delegate(IAsyncResult arr)
{
try
{
result = ((Func<IEnumerable<T>, IEnumerable<T>>)((AsyncResult)arr).AsyncDelegate).EndInvoke(arr);
}
catch (Exception ex)
{
if (errorCallback != null)
{
errorCallback(ex);
}
return;
}
//errors from inside here are the callbacks problem
//I think it would be confusing to report them
callback(result);
}),
null);
}
private static IEnumerable<T> InnerEnumerate<T>(IEnumerable<T> query)
{
foreach (var item in query) //the method hangs here while the query executes
{
yield return item;
}
}
}
И вы могли бы использовать его как это:
class Program
{
public static void Main(string[] args)
{
//this could be your linq query
var qry = TestSlowLoadingEnumerable();
//We begin the call and give it our callback delegate
//and a delegate to an error handler
AsynchronousQueryExecutor.Call(qry, HandleResults, HandleError);
Console.WriteLine("Call began on seperate thread, execution continued");
Console.ReadLine();
}
public static void HandleResults(IEnumerable<int> results)
{
//the results are available in here
foreach (var item in results)
{
Console.WriteLine(item);
}
}
public static void HandleError(Exception ex)
{
Console.WriteLine("error");
}
//just a sample lazy loading enumerable
public static IEnumerable<int> TestSlowLoadingEnumerable()
{
Thread.Sleep(5000);
foreach (var i in new int[] { 1, 2, 3, 4, 5, 6 })
{
yield return i;
}
}
}
Собирается пойти положить это на моем блоге сейчас, очень удобно.
Был ли приведенный ниже ответ подходящим для вас? – TheSoftwareJedi 2008-10-31 15:50:27
Проверьте Reactive Extensions for .NET на http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx, он предназначен для асинхронных запросов Linq. – 2010-03-24 06:34:19
Действительно, но не запросы Linq * к SQL *, о которых спрашивает автор. – 2012-01-17 09:03:16