8.5 异步搜索网络会话

问题

一些网络操作,诸如下载玩家配置或搜索可用的会话,会花费大量的时间。前面的教程中使用的是最简单的设置,这些操作会使程序暂停直至操作完成,这段时间中你想让玩家知道操作的信息!

解决方案

XNA为几乎所有需要时间完成的网络操作提供了异步选择。例如,NetworkSession. Find 方法的异步操作对应NetworkSession. BeginFind方法。

在异步操作的开始,XNA会创建第二个线程用于这个操作,让这个操作可以与主程序并行处理。这样做的优点是,你的主程序只需初始化异步操作,然后可以继续自己的处理。这让你可以向玩家提供任何运行在第二个线程中的异步操作的信息。

一旦异步操作完成,结果会传递到你指定的方法中,让你可以处理异步操作产生的结果。

工作原理

这个教程会解释如何使用NetworkSession.BeginFind方法,XNA中的其他的异步操作工作原理是相同的。

这个教程是教程8-3的异步版本,在那个教程中,程序开始处于SignIn状态并依次进入SearchSession, CreateSession和InSession状态。在这个教程中,你将添加一个Searching状态,当操作在后台运行时可以向用户提供信息:

public enum GameState
{
    SignIn, 
    SearchSession,
    Searching, 
    CreateSession, 
    InSession
}

开始异步操作

SearchSession状态很容易,因为它要做的只是初始化异步操作:

case GameState.SearchSession:
{
    NetworkSession.BeginFind(NetworkSessionType.SystemLink, 2, null, EndAsynchSearch, null);
    log.Add("ASynch search started - proceed to Searching"); 
    log.Add("Searching");
    currentGameState = GameState.Searching;
}
break;

NetworkSession.BeginFind方法会导致在后台创建第二个线程,这个线程与主程序并行进行搜索操作,这样带来的好处是主程序在运行到NetworkSession.BeginFind时无需等待(而使用NetworkSession.Find方法时需要),可以立即进入到Searching状态。

NetworkSession.BeginFind方法需要五个参数。前三个和NetworkSession. Find方法是相同的,可见教程8-3的解释。

要理解第四个参数,我需要解释当后台的搜索操作结束后会发生什么。第二个线程会调用你的方法之一并将它传递到结果。这意味着你必须指定应该调用哪个方法,这可以通过使用第四个参数做到。在本例中,当第二个线程结束后你指定它调用EndAsynchSearch方法,这个方法后面就会讲到。

最后一个参数让你识别异步操作,当在同一时间有多个异步操作的情况中这是很有用的。可见教程1—9看一下这个参数的例子。

在此期间. . .

当搜索在后台进行时,你可以自由地在Searching状态中做任何其他操作。在这个简单的例子中,每次调用Update方法时, 会在显示在屏幕的文字后面加上一个”.”。

case GameState.Searching: 
{
    log[log.Count - 1] +=”.” 
}
break;

NetworkSessions.EndFind

当运行在后台的第二个线程结束异步搜索后,它会调用在NetworkSession. BeginFind方法中第四个参数指定的方法。在前面的代码中,我指定的是EndAsynchSearch方法,具体代码如下,看起来比较复杂,但主要部分来自于前一个教程的SearchSession状态中的代码:

private void EndAsynchSearch(IAsyncResult result)
{
    AvailableNetworkSessionCollection activeSessions = NetworkSession.EndFind(result);
    if (activeSessions.Count == 0)
    {
        currentGameState = GameState.CreateSession;
        log.Add("No active sessions found - proceed to CreateSession");
    }
    else
    {
        AvailableNetworkSession sessionToJoin = activeSessions[0]; 
        networkSession = NetworkSession.Join(sessionToJoin);

        string myString = "Joined session hosted by " + sessionToJoin.HostGamertag; 
        myString += " with " + sessionToJoin.CurrentGamerCount.ToString() + " players";
        myString += " and " + sessionToJoin.OpenPublicGamerSlots.ToString() + " open player slots.";
        log.Add(myString);

        HookSessionEvents();
        currentGameState = GameState.InSession;
    }
}

这个方法将异步操作的结果作为参数。

对每个开始一个异步操作的方法,你都会找到一个方法可以处理它的结果。本例中开始异步操作的是NetworkSession.BeginFind方法,你可以将结果传递到NetworkSession.EndFind方法,这个方法将结果放在一个AvailableNetworkSessionCollection对象中。接下去的操作就和前一个教程一模一样了。

代码

下面是Update方法中的switch代码块,这个代码让程序从SignIn状态移动到SearchSession和Searching状态。EndAsynchSearch方法决定是否移动到CreateSession或 InSession状态。

switch (currentGameState)
{
    case GameState.SignIn:
    {
        if (Gamer.SignedInGamers.Count < 1)
        {
            Guide.ShowSignIn(1, false);
            log.Add("Opened User SignIn Interface");
            currentGameState = GameState.SearchSession; 
            log.Add(Gamer.SignedInGamers[0].Gamertag + " logged in - proceed to SearchSession");
        }
    }
    break;
    case GameState.SearchSession:
    {
        NetworkSession.BeginFind(NetworkSessionType.SystemLink, 2, null, EndAsynchSearch, null);
        log.Add("ASynch search started - proceed to Searching");
        log.Add("Searching");
        currentGameState = GameState.Searching;
    }
    break;
    case GameState.Searching:
    {
        log[log.Count - 1] += ".";
    }
    break;
    case GameState.CreateSession:
    {
        networkSession = NetworkSession.Create(NetworkSessionType.SystemLink,4, 16);
        networkSession.AllowHostMigration = true;
        networkSession.AllowJoinInProgress = false;
        log.Add("New session created");

        HookSessionEvents();
        currentGameState = GameState.InSession;
    }
    break;
    case GameState.InSession:
    {
        networkSession.Update();
    }
    break; 
}

发布时间:2009-11-11 11:01:25  阅读次数:2807

评论

由于网络审查方面的原因,本网站即日起关闭留言功能,若有什么问题可致信站长邮箱:fjphysics@qq.com。