网络——异步搜索网络会话

问题

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

解决方案

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; 

}

你可能感兴趣的:(搜索)