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

  1. Create a variable to track when a request for a StorageDevice is pending. In this case, we declare GameSaveRequested.
  2. 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.
  3. BeginShowStorageDeviceGuide returns an IAsyncResult interface that is used to determine when the asynchronous request is finished.
  4. Set your tracking variable to indicate a request is pending.
  5. When a request is pending, check IAsyncResult.IsCompleted periodically to determine when the storage device has been selected by the user.
  6. When IsCompleted is true, call EndShowStorageDeviceGuide, passing the IAsyncResult provided by BeginShowStorageDeviceGuide. The return value is the selected storage device.
  7. 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.
  8. 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

  1. 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.
  2. 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).
  3. 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.
  4. 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

  1. Create a variable to indicate that the Storage Device Guide is active, and set it to false.
  2. When a new StorageDevice is requested, set the variable to true, then call BeginShowStorageDeviceGuide. If the variable is already true, do not call BeginShowStorageDeviceGuide.
  3. Call Game.Tick until the IAsyncResult returned by BeginShowStorageDeviceGuide is completed.
  4. When IsCompleted is true, call EndShowStorageDeviceGuide, passing the IAsyncResult provided by BeginShowStorageDeviceGuide. The return value is the selected storage device.
  5. 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.
  6. 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 );
    }
    
}
Show: