CNA-GAP-070: NetworkSession's Local, LocalWithLeaderboards and SystemLink Begin/End pairs are synchronous: Begin runs the callback and returns a completed result, and End does the work on the caller's thread
Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit c1c316b9; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
For Local, LocalWithLeaderboards and SystemLink sessions, BeginCreate, BeginFind and BeginJoin run the callback inline and return a completed result; End* then blocks: 150 ms for a SystemLink Find, up to 5 s for a SystemLink Join.
- Identifier
CNA-GAP-070- Category
- Functional gap
- Subsystem
- Networking & gamer services
- Status
- Open
- Verified against
- CNA
c1c316b9(c1c316b9c7a846ce8002809c151fcd1af14942c9) - Evidence basis
- Source-verified: read at TARGET, not executed
- Tests touching this area
- Yes: see Current tests
- Affected contract
- Microsoft::Xna::Framework::Net::NetworkSession::BeginCreate/BeginFind/BeginJoin and the matching End* methods for Local, LocalWithLeaderboards and SystemLink sessions
Expected behaviour
XNA 4.0 (read from the decompiled Microsoft.Xna.Framework.Net assembly and its async dispatcher; not executed) registers each Begin* operation as pending: IsCompleted stays false until a dispatcher thread finishes it, the wait handle is signalled then, the AsyncCallback is queued to the thread pool, and End* returns the finished result.
Actual behaviour at TARGET
In NetworkSession.cpp a NetworkSessionAction starts complete (IsCompleted true, wait handle signalled, CompletedSynchronously true). For every session type except PlayerMatch and Ranked, BeginCreate, BeginFind and BeginJoin invoke the AsyncCallback inline (InvokeActiveActionCallback) before returning. The work then runs in End* on the caller's thread. On native builds, EndFind waits the fixed 150 ms SystemLink discovery window, and EndJoin pumps the joined session for up to 5 s until the host's welcome arrives. A game that polls IsCompleted every frame and calls End* when it turns true therefore stalls there. Service-backed PlayerMatch/Ranked Create, Find and Join, and BeginJoinInvited, are genuinely pending (QueueOnlineSession, QueueServiceSearch): IsCompleted stays false until the CNA service answers, so they are not part of this entry.
Source locations
modules/net/src/Xna/NetworkSession.cpp— NetworkSessionAction constructor, InvokeActiveActionCallback, EndFind, EndJoinmodules/net/include/Microsoft/Xna/Framework/Net/NetworkSession.hpp— NetworkSessionAction::completedSynchronously_ defaults to truemodules/net/src/Internal/ENetDiscoveryService.cpp— FindSessions and its 150 ms search window
Evidence
Read at c1c316b9; nothing executed. The published deep dive on network sessions records the completed-at-construction behaviour as an implementation oddity; this entry records its consequence for callers who port XNA's asynchronous pattern. Reported as a narrow restore by the D2 dismissal reviewer, who had confirmed that CompletedSynchronously being false matches XNA, and re-verified by the orchestrator.
Re-verified at b0e97bb1: b7754e45f (GS-007e2b) made service-backed PlayerMatch and Ranked Create, Find and Join, and BeginJoinInvited, genuinely pending; Local, LocalWithLeaderboards and SystemLink Begin calls still complete inline, now reporting CompletedSynchronously true. Not executed.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
NetworkSessionTests.BeginCreateInvokesCallbackExactlyOnceWithCorrectIdentity pins the inline callback; no test measures the time EndFind or EndJoin block.
Blast radius
Games and samples that start a Begin* operation and keep rendering while they wait: with CNA the wait moves into End*, so the frame that calls it stalls for up to the discovery window or the join timeout.
Workaround
Call End* from a worker thread or accept the stall on a loading screen; do not call it from the frame loop.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Internals
- Networking internals
- Known issues
- Functional gap index