LINQ自体には実際にはこれがありませんが、フレームワーク自体にはあります...独自の非同期クエリエグゼキュータを30行程度で簡単にロールできます...実際、私はこれを一緒に投げました:)
編集:これを書くことを通して、私は彼らがそれを実装しなかった理由を発見しました。スコープがローカルであるため、匿名タイプを処理できません。したがって、コールバック関数を定義する方法はありません。 多くのlinqtosqlのものがselect句でそれらを作成するので、これはかなり重要なことです。以下の提案はどれも同じ運命をたどるので、私はまだこれが最も使いやすいと思います!
編集:唯一の解決策は、匿名タイプを使用しないことです。コールバックをIEnumerable(タイプargsなし)を取得するものとして宣言し、リフレクションを使用してフィールドにアクセスできます(ICK !!)。別の方法は、コールバックを「動的」として宣言することです...ああ...待ってください...それはまだ出ていません。:)これは、ダイナミックを使用する方法のもう1つの適切な例です。虐待と呼ぶ人もいます。
これをユーティリティライブラリにスローします。
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;
}
}
}
行くつもりです、これを今私のブログに載せてください、かなり便利です。