CNA-GAP-070: NetworkSession's Begin/End pairs are synchronous: the result is complete and the callback has run when Begin returns, 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 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
NetworkSession's BeginCreate, BeginFind and BeginJoin each return an already-completed IAsyncResult (CompletedSynchronously still false) and run their AsyncCallback inline; End* then blocks the caller: 150 ms for a native SystemLink Find, up to 5 s for a native Join. BeginJoinInvited is not part of this: it refuses outright.
- Identifier
CNA-GAP-070- Category
- Functional gap
- Subsystem
- Networking & gamer services
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - 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/BeginJoinInvited and the matching End* methods
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 the NetworkSessionAction is constructed already complete (IsCompleted true, wait handle signalled) and BeginCreate, BeginFind and BeginJoin invoke the AsyncCallback inline on the calling thread before they return, while CompletedSynchronously stays false as in XNA (the header comment says the class "never completes synchronously"). The real work runs in End* on the caller's thread: on native builds EndFind waits a fixed 150 ms discovery window for SystemLink and EndJoin pumps the 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 blocks there. The deviation is deliberate and recorded in source comments (a pending action hung the polling loop once a GamerServicesComponent existed). BeginJoinInvited (both overloads) is the exception: it throws GamerServicesNotAvailableException before creating an action, and EndJoinInvited throws ArgumentException.
Source locations
modules/net/src/Xna/NetworkSession.cpp— NetworkSessionAction constructor, InvokeActiveActionCallback, EndFind, EndJoinmodules/net/include/Microsoft/Xna/Framework/Net/NetworkSession.hpp— NetworkSessionAction::getCompletedSynchronouslyProperty commentmodules/net/src/Internal/ENetDiscoveryService.cpp— FindSessions and its 150 ms search window
Evidence
Read at 009d40f5; 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.
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