Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 嵌套异步任务_C#_Asp.net_Task Parallel Library - Fatal编程技术网

C# 嵌套异步任务

C# 嵌套异步任务,c#,asp.net,task-parallel-library,C#,Asp.net,Task Parallel Library,我想知道是否有可能改进此代码以获得更好的性能。我不熟悉服务器端的整个异步工作,所以请在这里耐心听我说: 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 /

我想知道是否有可能改进此代码以获得更好的性能。我不熟悉服务器端的整个异步工作,所以请在这里耐心听我说:

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()阻止主线程


有什么方法可以使任务同时运行吗?

考虑在GetGame页面中使用,而不是在Task中使用。继续使用理想情况下,您可以使这些操作一直异步:

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
});

没有LINQ的替代解决方案(尽管我喜欢Reed Copsey的解决方案)。但是,请注意,正如注释中所指出的,此解决方案通过将对
GetPlayerDetailsAsync()
的调用封装在由
Task.Run()
创建的任务中而引入了开销

需要.NET 4.5和C#5

con.GetGame(id,game=>{
var tasks=新列表();
foreach(游戏中的玩家p.Team1)
{
tasks.Add(Task.Run(async()=>p.SomeExtraDetails=wait-getPlayerDetails=wait-getPlayerDetailsSync(p.Id));
}
Task.WaitAll(tasks.ToArray());
});
专用任务GetPlayerDetailsAsync(双playerId)
{
返回con.GetPlayerAsync(playerId);
});

此外,为了在.NET 4.5中赶上基于任务的异步模式(TAP),我强烈建议阅读:由微软的Stephen Toub编写。

您能使用C#5.0吗?另外,为什么您的一些方法使用continuations和一些
Task
s?我认为如果你保持一致会更好。@svick我使用的是VS2012,但我相信它是.NET 4.5 atm。@Johan这不是打字错误-它是C#5(语言)和.NET 4.5(框架);)你介意告诉我它是如何在我的例子中实现的吗?@ Johan考虑其他答案并尽量避免复制粘贴。programming@IlyaBursov这与复制粘贴编程无关。这是关于理解您的确切意思以及如何实际使用
Parallel.ForEach()
.Parallel.ForEach(game.Team1,p=>{p.SomeExtraDetails=GetPlayerDetails(p.Id);})上面答案中的复制粘贴`非常感谢您的详细回答。我尝试了上一个示例,但在
返回任务时遇到异常。结果
当另一个写入操作挂起时,无法调用Write方法。“
@Johan听起来你的GetPlayer方法不是线程安全的;)@Johan在不知道发生了什么的情况下很难判断-顺便说一句,如果你能让它工作的话,上面的第一个选项将是非常好的(完全没有阻塞)好的,我已经尝试了第一个。await关键字通过
突出显示,'await'运算符只能用于标记有'async'修饰符的方法或lambda
@Johan您需要将您的方法设置为异步方法。这很有效,看起来很不错,但不必要地使用线程池。。。Run将依赖TP线程来运行任务,而我的版本避免了这一点that@ReedCopsey我完全同意这一点。我应该在写答案的时候指出这一点。但是,我现在已经更新了我的答案,因此很明显,这个替代实现在多次调用
Task.Run()
时会带来开销。
// 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);
    });

});
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);
});