3

我想知道是否可以改进此代码以获得更好的性能。我对服务器端的整个异步操作很陌生,所以请在这里耐心等待:

con.GetGame(id, game => {

    foreach(Player p in game.Team1)
    {
        p.SomeExtraDetails = GetPlayerDetails(p.Id);
    }

    // I would like the player data to be set on all players
    // before ending up here
});

private PlayerDetails GetPlayerDetails(double playerId)
{
    var task = con.GetPlayer(playerId);

    PlayerDetails ret = null;

    Task continuation = task.ContinueWith(t =>
    {
        ret = t.Result;
    });

    continuation.Wait();

    return ret;
}

如果我做对了,就continuation.Wait();阻塞主线程。

有没有办法让任务同时运行?

4

3 回答 3

7

理想情况下,您应该使这些操作一直异步:

private Task<PlayerDetails> GetPlayerDetailsAsync(double playerId)
{
    return con.GetPlayer(playerId);
}

con.GetGame(id, game => {
    var tasks = game.Team1
                    .Select(p => new { Player=p, Details=GetPlayerDetailsAsync(p.Id)})
                    .ToList(); // Force all tasks to start...

    foreach(var t in tasks)
    {
        t.Player.SomeExtraDetails = await t.Details;
    }

    // all player data is now set on all players
});

如果这不是一个选项(即:您没有使用 VS 2012),您可以将代码简化为:

// This is a more efficient version of your existing code
private PlayerDetails GetPlayerDetails(double playerId)
{
    var task = con.GetPlayer(playerId);
    return task.Result;
}

con.GetGame(id, game => {
    // This will run all at once, but block until they're done
    Parallel.ForEach(game.Team1, p =>
    {
        p.SomeExtraDetails = GetPlayerDetails(p.Id);
    });

});
于 2013-10-18T23:57:00.133 回答
0

考虑在 GetGame 页面中使用Parallel.ForEach而不是 Task.ContinueWith

于 2013-10-18T23:52:17.040 回答
0

没有 LINQ 的替代解决方案(尽管我喜欢 Reed Copsey 的解决方案)。但是,请注意,正如评论中所指出的,此解决方案通过封装对GetPlayerDetailsAsync()Task.Run().

需要 .NET 4.5 和 C# 5。

con.GetGame(id, game => {

    var tasks = new List<Task>();

    foreach(Player p in game.Team1)
    {
        tasks.Add(Task.Run(async () => p.SomeExtraDetails = await GetPlayerDetailsAsync(p.Id)));
    }

    Task.WaitAll(tasks.ToArray());
});

private Task<PlayerDetails> GetPlayerDetailsAsync(double playerId)
{
    return con.GetPlayerAsync(playerId);
});

此外,为了赶上 .NET 4.5 的基于任务的异步模式 (TAP),我强烈建议您阅读:基于任务的异步模式- Microsoft 的 Stephen Toub。

于 2013-10-19T00:12:26.207 回答