虽然 LINQ 本身并没有真正具有此功能,但框架本身确实...您可以轻松地在 30 行左右滚动您自己的异步查询执行器...事实上,我只是为您把它放在一起:)
编辑:通过写这篇文章,我发现了他们为什么没有实现它。它不能处理匿名类型,因为它们是本地的。因此,您无法定义回调函数。 这是一件非常重要的事情,因为很多 linq to sql 的东西在 select 子句中创建它们。以下任何建议都遭受同样的命运,所以我仍然认为这个是最容易使用的!
编辑:唯一的解决方案是不使用匿名类型。您可以将回调声明为仅采用 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;
}
}
}
现在打算把它放在我的博客上,非常方便。