3

非同期メソッドがあります

 public static Task<JObject> GetUser(NameValueCollection parameters)
        {
            return CallMethodApi("users.get", parameters, CallType.HTTPS);
        }

そして、私は以下のメソッドを書きます

public static IEnumerable<JObject> GetUsers(IEnumerable<string> usersUids, Field fields)
{
    foreach(string uid in usersUids)
    {
        var parameters = new NameValueCollection
                             {
                                 {"uids", uid},
                                 {"fields", FieldsUtils.ConvertFieldsToString(fields)}
                             };
        yield return GetUser(parameters).Result;
    }
}

このメソッドは非同期ですか?Parallel.ForEachを使用してこれを作成するにはどうすればよいですか?

4

2 に答える 2

4

こんな感じ。

public static IEnumerable<JObject> GetUsers(IEnumerable<string> usersUids, Field fields)
{
    var results = new List<JObject>
    Parallel.ForEach(usersUids, uid => {
        var parameters = new NameValueCollection
                             {
                                 {"uids", uid},
                                 {"fields", FieldsUtils.ConvertFieldsToString(fields)}
                             };
        var user = GetUser(parameters).Result;
        lock(results)
            results.Add(user);
    });
    return results;
}

注:結果は、期待したものと同じ順序にはなりません。

于 2012-06-21T21:17:59.450 に答える
2

あなたのメソッドは非同期ではありません。GetUserメソッドがすでに非同期タスクを開始していると仮定すると、タスクを開始するためだけに追加Parallel.ForEachのスレッドを使用しますが、これはおそらくあなたが望むものではありません。

代わりに、おそらくやりたいことは、すべてのタスクを開始し、それらが終了するのを待つことです。

public static IEnumerable<JObject> GetUsers(IEnumerable<string> usersUids, Field fields)
{
    var tasks = usersUids.Select(
        uid =>
        {
            var parameters = new NameValueCollection
            {
                {"uids", uid},
                {"fields", FieldsUtils.ConvertFieldsToString(fields)}
            };
            return GetUser(parameters);
        }
    ).ToArray();

    Task.WaitAll(tasks);

    var result = new JObject[tasks.Length];
    for (var i = 0; i < tasks.Length; ++i)
        result[i] = tasks[i].Result;

    return result;
}

それらを並行して開始したい場合は、PLINQを使用できます。

    var tasks = usersUids.AsParallel().AsOrdered().Select(
        uid =>
        {
            var parameters = new NameValueCollection
            {
                {"uids", uid},
                {"fields", FieldsUtils.ConvertFieldsToString(fields)}
            };
            return GetUser(parameters);
        }
    ).ToArray();

両方のコードスニペットは、uidと返されたオブジェクトの相対的な順序を保持します-などresult[0]に対応します。usersUids[0]

于 2012-06-21T23:56:47.443 に答える