How to: Get a StorageDevice Asynchronously
This example demonstrates how to call BeginShowStorageDeviceGuide and EndShowStorageDeviceGuide to get a StorageDevice object asynchronously.
To get a StorageDevice asynchronously using IsCompleted
- Create a variable to track when a request for a StorageDevice is pending. In this case, we declare GameSaveRequested.
- When the user needs to access the StorageDevice for the first time (for example, to save a game) call BeginShowStorageDeviceGuide, specifying which player has requested the save.
- BeginShowStorageDeviceGuide returns an IAsyncResult interface that is used to determine when the asynchronous request is finished.
- Set your tracking variable to indicate a request is pending.
- When a request is pending, check IAsyncResult.IsCompleted periodically to determine when the storage device has been selected by the user.
- When IsCompleted is true, call EndShowStorageDeviceGuide, passing the IAsyncResult provided by BeginShowStorageDeviceGuide. The return value is the selected storage device.
- Use IsConnected to ensure that a valid device was chosen (if the user declines to select a device, or the device is removed, IsConnected will be false). If the StorageDevice is connected, use it to load or save data.
- Reset your tracking variable.
// Note: Before you can build this file in a project, you must
// add a reference to System.xml. To to this, right-click
// on References in Solution Explorer and click Add Reference.
// In the .NET pane, scroll down and select System.Xml.
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using System.IO;
using System.Xml.Serialization;
IAsyncResult result;
Object stateobj;
bool GameSaveRequested = false;
protected override void Update( GameTime gameTime )
{
// Allows the default game to exit on Xbox 360 and Windows
if (GamePad.GetState( PlayerIndex.One ).Buttons.Back == ButtonState.Pressed)
this.Exit();
if (GamePad.GetState( PlayerIndex.One ).Buttons.A == ButtonState.Pressed)
{
// Set the request flag
GameSaveRequested = true;
result = StorageDevice.BeginShowStorageDeviceGuide( PlayerIndex.One, null, null );
}
// If a save is pending, save as soon as the
// storage device is chosen
if ((GameSaveRequested) && (result.IsCompleted))
{
StorageDevice device = StorageDevice.EndShowStorageDeviceGuide( result );
if (device.IsConnected)
{
DoSaveGame( device );
}
// Reset the request flag
GameSaveRequested = false;
}
base.Update( gameTime );
}
To get a StorageDevice asynchronously using an AsyncCallback
- Create an AsyncCallback object that represents the method that will be called when the player chooses a device. That function must take an IAsyncResult as a parameter and return void.
- When the user needs to access the StorageDevice for the first time (for example, to save a game) call BeginShowStorageDeviceGuide, specifying which player has requested the save, and your AsyncCallback object. You may optionally pass a tracking object to identify the request (or null).
- In your callback method, call EndShowStorageDeviceGuide, passing the same IAsyncResult that was passed into the callback method. The return value is the selected storage device.
- Use IsConnected to ensure that a valid device was chosen (if the user declines to select a device, or the device is removed, IsConnected will be false). If the StorageDevice is connected, use it to load or save data.
// Note: Before you can build this file in a project, you must
// add a reference to System.xml. To to this, right-click
// on References in Solution Explorer and click Add Reference.
// In the .NET pane, scroll down and select System.Xml.
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using System.IO;
using System.Xml.Serialization;
IAsyncResult result;
Object stateobj;
bool GameSaveRequested = false;
protected override void Update( GameTime gameTime )
{
// Allows the default game to exit on Xbox 360 and Windows
if (GamePad.GetState( PlayerIndex.One ).Buttons.Back == ButtonState.Pressed)
this.Exit();
if (GamePad.GetState( PlayerIndex.One ).Buttons.B == ButtonState.Pressed)
{
// Reset the device
device = null;
AsyncCallback ac = new AsyncCallback( this.GetDevice );
stateobj = (Object)"GetDevice for Player One";
StorageDevice.BeginShowStorageDeviceGuide(
PlayerIndex.One, ac, stateobj );
}
base.Update( gameTime );
}
StorageDevice device;
void GetDevice( IAsyncResult result )
{
device = StorageDevice.EndShowStorageDeviceGuide( result );
if (device.IsConnected)
{
DoSaveGame( device );
}
}
To get a StorageDevice asynchronously using Game.Tick and IsCompleted
- Create a variable to indicate that the Storage Device Guide is active, and set it to false.
- When a new StorageDevice is requested, set the variable to true, then call BeginShowStorageDeviceGuide. If the variable is already true, do not call BeginShowStorageDeviceGuide.
- Call Game.Tick until the IAsyncResult returned by BeginShowStorageDeviceGuide is completed.
- When IsCompleted is true, call EndShowStorageDeviceGuide, passing the IAsyncResult provided by BeginShowStorageDeviceGuide. The return value is the selected storage device.
- Use IsConnected to ensure that a valid device was chosen (if the user declines to select a device, or the device is removed, IsConnected will be false). If the StorageDevice is connected, use it to load or save data.
- Reset your tracking variable.
The Complete Example
// Note: Before you can build this file in a project, you must
// add a reference to System.xml. To to this, right-click
// on References in Solution Explorer and click Add Reference.
// In the .NET pane, scroll down and select System.Xml.
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using System.IO;
using System.Xml.Serialization;
using Microsoft.Xna.Framework.Content;
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
ContentManager content;
public Game1()
{
graphics = new GraphicsDeviceManager( this );
content = new ContentManager( Services );
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadGraphicsContent( bool loadAllContent )
{
if (loadAllContent)
{
// TODO: Load any ResourceManagementMode.Automatic content
}
}
protected override void UnloadGraphicsContent( bool unloadAllContent )
{
if (unloadAllContent == true)
{
content.Unload();
}
}
bool ShowingStorageDeviceGuide = false;
IAsyncResult result;
Object stateobj;
bool GameSaveRequested = false;
protected override void Update( GameTime gameTime )
{
// Allows the default game to exit on Xbox 360 and Windows
if (GamePad.GetState( PlayerIndex.One ).Buttons.Back == ButtonState.Pressed)
this.Exit();
if (GamePad.GetState( PlayerIndex.One ).Buttons.A == ButtonState.Pressed)
{
// Set the request flag
GameSaveRequested = true;
result = StorageDevice.BeginShowStorageDeviceGuide( PlayerIndex.One, null, null );
}
if (GamePad.GetState( PlayerIndex.One ).Buttons.B == ButtonState.Pressed)
{
// Reset the device
device = null;
AsyncCallback ac = new AsyncCallback( this.GetDevice );
stateobj = (Object)"GetDevice for Player One";
StorageDevice.BeginShowStorageDeviceGuide(
PlayerIndex.One, ac, stateobj );
}
// If a save is pending, save as soon as the
// storage device is chosen
if ((GameSaveRequested) && (result.IsCompleted))
{
StorageDevice device = StorageDevice.EndShowStorageDeviceGuide( result );
if (device.IsConnected)
{
DoSaveGame( device );
DoLoadGame( device );
DoCreate( device );
DoOpen( device );
DoCopy( device );
DoEnumerate( device );
DoRename( device );
DoDelete( device );
DoOpenFile();
}
// Reset the request flag
GameSaveRequested = false;
}
if (GamePad.GetState( PlayerIndex.One ).Buttons.X == ButtonState.Pressed)
{
// make sure we don't call BeginShowStorageDeviceGuide when the guide
// is already being shown
if (!ShowingStorageDeviceGuide)
{
ShowingStorageDeviceGuide = true;
// reset the device
device = null;
result = StorageDevice.BeginShowStorageDeviceGuide( PlayerIndex.One, null, null );
while (!result.IsCompleted)
{
// Call Update and Draw to draw the guide
this.Tick();
}
device = StorageDevice.EndShowStorageDeviceGuide(result);
if (device.IsConnected)
{
DoSaveGame( device );
DoLoadGame( device );
DoCreate( device );
DoOpen( device );
DoCopy( device );
DoEnumerate( device );
DoRename( device );
DoDelete( device );
DoOpenFile();
}
ShowingStorageDeviceGuide = false;
}
}
base.Update( gameTime );
}
StorageDevice device;
void GetDevice( IAsyncResult result )
{
device = StorageDevice.EndShowStorageDeviceGuide( result );
if (device.IsConnected)
{
DoSaveGame( device );
DoLoadGame( device );
DoCreate( device );
DoOpen( device );
DoCopy( device );
DoEnumerate( device );
DoRename( device );
DoDelete( device );
DoOpenFile();
}
}
protected override void Draw( GameTime gameTime )
{
graphics.GraphicsDevice.Clear( Color.CornflowerBlue );
base.Draw( gameTime );
}
[Serializable]
public struct SaveGameData
{
public string PlayerName;
public Vector2 AvatarPosition;
public int Level;
public int Score;
}
private static void DoSaveGame( StorageDevice device )
{
// Create the data to save
SaveGameData data = new SaveGameData();
data.PlayerName = "Hiro";
data.AvatarPosition = new Vector2( 360, 360 );
data.Level = 11;
data.Score = 4200;
// Open a storage container
StorageContainer container =
device.OpenContainer( "StorageDemo" );
// Get the path of the save game
string filename = Path.Combine( container.Path, "savegame.sav" );
// Open the file, creating it if necessary
FileStream stream = File.Open( filename, FileMode.OpenOrCreate );
// Convert the object to XML data and put it in the stream
XmlSerializer serializer = new XmlSerializer( typeof( SaveGameData ) );
serializer.Serialize( stream, data );
// Close the file
stream.Close();
// Dispose the container, to commit changes
container.Dispose();
}
private static void DoLoadGame( StorageDevice device )
{
// Open a storage container
StorageContainer container =
device.OpenContainer( "StorageDemo" );
// Get the path of the save game
string filename = Path.Combine( container.Path, "savegame.sav" );
// Check to see if the save exists
if (!File.Exists( filename ))
// Notify the user there is no save
return;
// Open the file
FileStream stream = File.Open( filename, FileMode.OpenOrCreate,
FileAccess.Read );
// Read the data from the file
XmlSerializer serializer = new XmlSerializer( typeof( SaveGameData ) );
SaveGameData data = (SaveGameData)serializer.Deserialize( stream );
// Close the file
stream.Close();
// Dispose the container
container.Dispose();
// Report the data to the console
Console.WriteLine( "Name: " + data.PlayerName );
Console.WriteLine( "Level: " + data.Level.ToString() );
Console.WriteLine( "Score: " + data.Score.ToString() );
Console.WriteLine( "Position: " + data.AvatarPosition.ToString() );
}
private static void DoCreate( StorageDevice device )
{
// Open a storage container
StorageContainer container =
device.OpenContainer( "StorageDemo" );
// Add the container path to our filename
string filename = Path.Combine( container.Path, "demobinary.sav" );
// Create a new file
if (!File.Exists( filename ))
{
FileStream file = File.Create( filename );
file.Close();
}
// Dispose the container, to commit the data
container.Dispose();
}
private static void DoOpen( StorageDevice device )
{
// Open a storage container
StorageContainer container =
device.OpenContainer( "StorageDemo" );
// Add the container path to our filename
string filename = Path.Combine( container.Path, "demobinary.sav" );
FileStream file = File.Open( filename, FileMode.Open );
file.Close();
// Dispose the container
container.Dispose();
}
private static void DoCopy( StorageDevice device )
{
// Open a storage container
StorageContainer container =
device.OpenContainer( "StorageDemo" );
// Add the container path to our filename
string filename = Path.Combine( container.Path, "demobinary.sav" );
string copyfilename = Path.Combine( container.Path, "copybinary.sav" );
File.Copy( filename, copyfilename, true );
// Dispose the container, to commit the change
container.Dispose();
}
private static void DoRename( StorageDevice device )
{
// Open a storage container
StorageContainer container =
device.OpenContainer( "StorageDemo" );
// Add the container path to our filename
string oldfilename = Path.Combine( container.Path, "demobinary.sav" );
string newfilename = Path.Combine( container.Path, "renamebinary.sav" );
if (!File.Exists( newfilename ))
File.Move( oldfilename, newfilename );
// Dispose the container, to commit the change
container.Dispose();
}
private static void DoEnumerate( StorageDevice device )
{
// Open a storage container
StorageContainer container =
device.OpenContainer( "StorageDemo" );
ICollection<string> FileList = Directory.GetFiles( container.Path );
// Dispose the container
container.Dispose();
}
private static void DoDelete( StorageDevice device )
{
// Open a storage container
StorageContainer container =
device.OpenContainer( "StorageDemo" );
// Add the container path to our filename
string filename = Path.Combine( container.Path, "demobinary.sav" );
// Delete the new file.
if (File.Exists( filename ))
File.Delete( filename );
// Dispose the container, to commit the change
container.Dispose();
}
private static void DoOpenFile()
{
FileStream file = OpenTitleFile(
"Sprite.dds", FileMode.Open, FileAccess.Read );
Console.WriteLine( "File Size: " + file.Length );
file.Close();
}
private static FileStream OpenTitleFile(
string filename, FileMode mode, FileAccess access )
{
string fullpath = Path.Combine( StorageContainer.TitleLocation, filename );
return File.Open( fullpath, mode, access );
}
}
See Also
Concepts
Storage Overview
Xbox 360 Programming Considerations
Reference
StorageDevice
BeginShowStorageDeviceGuide
EndShowStorageDeviceGuide
AsyncCallback
IAsyncResult