Walkthrough: Caching Application Data in a WPF Application

Caching enables you to store data in memory for rapid access. When the data is accessed again, applications can get the data from the cache instead retrieving it from the original source. This can improve performance and scalability. In addition, caching makes data available when the data source is temporarily unavailable.

The .NET Framework provides classes that enable you to use caching in .NET Framework applications. These classes are located in the System.Runtime.Caching namespace.

Note

The System.Runtime.Caching namespace is new in the .NET Framework 4. This namespace makes caching is available to all .NET Framework applications. In previous versions of the .NET Framework, caching was available only in the System.Web namespace and therefore required a dependency on ASP.NET classes.

This walkthrough shows you how to use the caching functionality that is available in the .NET Framework as part of a Windows Presentation Foundation (WPF) application. In the walkthrough, you cache the contents of a text file.

Tasks illustrated in this walkthrough include the following:

  • Creating a WPF application project.

  • Adding a reference to the .NET Framework 4.

  • Initializing a cache.

  • Adding a cache entry that contains the contents of a text file.

  • Providing an eviction policy for the cache entry.

  • Monitoring the path of the cached file and notifying the cache instance about changes to the monitored item.

Prerequisites

In order to complete this walkthrough, you will need:

  • Microsoft Visual Studio 2010.

  • A text file that contains a small amount of text. (You will display the contents of the text file in a message box.) The code illustrated in the walkthrough assumes that you are working with the following file:

    c:\cache\cacheText.txt

    However, you can use any text file and make small changes to the code in this walkthrough.

Creating a WPF Application Project

You will start by creating a WPF application project.

To create a WPF application

  1. Start Visual Studio.

  2. In the File menu, click New, and then click New Project.

    The New Project dialog box is displayed.

  3. Under Installed Templates, select the programming language you want to use (Visual Basic or Visual C#).

  4. In the New Project dialog box, select WPF Application.

    Note

    If you do not see the WPF Application template, make sure that you are targeting a version of the .NET Framework that supports WPF. In the New Project dialog box, select .NET Framework 4 from the list.

  5. In the Name text box, enter a name for your project. For example, you can enter WPFCaching.

  6. Select the Create directory for solution check box.

  7. Click OK.

    The WPF Designer opens in Design view and displays the MainWindow.xaml file. Visual Studio creates the My Project folder, the Application.xaml file, and the MainWindow.xaml file.

Targeting the .NET Framework and Adding a Reference to the Caching Assemblies

By default, WPF applications target the .NET Framework 4 Client Profile. To use the System.Runtime.Caching namespace in a WPF application, the application must target the .NET Framework 4 (not the .NET Framework 4 Client Profile) and must include a reference to the namespace. 

Therefore, the next step is to change the .NET Framework target and add a reference to the System.Runtime.Caching namespace.

Note

The procedure for changing the .NET Framework target is different in a Visual Basic project and in a Visual C# project.

To change the target .NET Framework in Visual Basic

  1. In Solutions Explorer, right-click the project name, and then click Properties.

    The properties window for the application is displayed.

  2. Click the Compile tab.

  3. At the bottom of the window, click Advanced Compile Options….

    The Advanced Compiler Settings dialog box is displayed.

  4. In the Target framework (all configurations) list, select .NET Framework 4. (Do not select .NET Framework 4 Client Profile.)

  5. Click OK.

    The Target Framework Change dialog box is displayed.

  6. In the Target Framework Change dialog box, click Yes.

    The project is closed and is then reopened.

  7. Add a reference to the caching assembly by following these steps:

    1. In Solution Explorer, right-click the name of the project and then click Add Reference.

    2. Select the .NET tab, select System.Runtime.Caching, and then click OK.

To change the target .NET Framework in a Visual C# project

  1. In Solution Explorer, right-click the project name and then click Properties.

    The properties window for the application is displayed.

  2. Click the Application tab.

  3. In the Target framework list, select .NET Framework 4. (Do not select .NET Framework 4 Client Profile.)

  4. Add a reference to the caching assembly by following these steps:

    1. Right-click the References folder and then click Add Reference.

    2. Select the .NET tab, select System.Runtime.Caching, and then click OK.

Adding a Button to the WPF Window

Next, you will add a button control and create an event handler for the button's Click event. Later you will add code to so when you click the button, the contents of the text file are cached and displayed.

To add a button control

  1. In Solution Explorer, double-click the MainWindow.xaml file to open it.

  2. From the Toolbox, under Common WPF Controls, drag a Button control to the MainWindow window.

  3. In the Properties window, set the Content property of the Button control to Get Cache.

Initializing the Cache and Caching an Entry

Next, you will add the code to perform the following tasks:

  • Create an instance of the cache class—that is, you will instantiate a new MemoryCache object.

  • Specify that the cache uses a HostFileChangeMonitor object to monitor changes in the text file.

  • Read the text file and cache its contents as a cache entry.

  • Display the contents of the cached text file.

To create the cache object

  1. Double-click the button you just added in order to create an event handler in the MainWindow.xaml.cs or MainWindow.Xaml.vb file.

  2. At the top of the file (before the class declaration), add the following Imports (Visual Basic) or using (C#) statements:

    using System.Runtime.Caching;
    using System.IO;
    
    Imports System.Runtime.Caching
    Imports System.IO
    
  3. In the event handler, add the following code to instantiate the cache object:

    ObjectCache cache = MemoryCache.Default;
    
    Dim cache As ObjectCache = MemoryCache.Default
    

    The ObjectCache class is a built-in class that provides an in-memory object cache.

  4. Add the following code to read the contents of a cache entry named filecontents:

    Dim fileContents As String = TryCast(cache("filecontents"), String)
    
    string fileContents = cache["filecontents"] as string;
    
  5. Add the following code to check whether the cache entry named filecontents exists:

    If fileContents Is Nothing Then
    
    End If
    
    if (fileContents == null)
    {
    
    }
    

    If the specified cache entry does not exist, you must read the text file and add it as a cache entry to the cache.

  6. In the if/then block, add the following code to create a new CacheItemPolicy object that specifies that the cache entry expires after 10 seconds.

    Dim policy As New CacheItemPolicy()
    policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10.0)
    
    CacheItemPolicy policy = new CacheItemPolicy();
    policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10.0);
    

    If no eviction or expiration information is provided, the default is InfiniteAbsoluteExpiration, which means the cache entries never expire based only on an absolute time. Instead, cache entries expire only when there is memory pressure. As a best practice, you should always explicitly provide either an absolute or a siding expiration.

  7. Inside the if/then block and following the code you added in the previous step, add the following code to create a collection for the file paths that you want to monitor, and to add the path of the text file to the collection:

    Dim filePaths As New List(Of String)()
    filePaths.Add("c:\cache\cacheText.txt")
    
    List<string> filePaths = new List<string>();
    filePaths.Add("c:\\cache\\cacheText.txt");
    

    Note

    If the text file you want to use is not c:\cache\cacheText.txt, specify the path where the text file is that you want to use.

  8. Following the code that you added in the previous step, add the following code to add a new HostFileChangeMonitor object to the collection of change monitors for the cache entry:

    policy.ChangeMonitors.Add(New HostFileChangeMonitor(filePaths))
    
    policy.ChangeMonitors.Add(new HostFileChangeMonitor(filePaths));
    

    The HostFileChangeMonitor object monitors the text file's path and notifies the cache if changes occur. In this example, the cache entry will expire if the content of the file changes.

  9. Following the code that you added in the previous step, add the following code to read the contents of the text file:

    fileContents = File.ReadAllText("c:\cache\cacheText.txt") & vbCrLf & DateTime.Now.ToString()
    
    fileContents = File.ReadAllText("c:\\cache\\cacheText.txt") + + "\n" + DateTime.Now; 
    

    The date and time timestamp is added so that you will be able to see when the cache entry expires.

  10. Following the code that you added in the previous step, add the following code to insert the contents of the file into the cache object as a CacheItem instance:

    cache.Set("filecontents", fileContents, policy)
    
    cache.Set("filecontents", fileContents, policy);
    

    You specify information about how the cache entry should be evicted by passing the CacheItemPolicy object that you created earlier as a parameter.

  11. After the if/then block, add the following code to display the cached file content in a message box:

    MessageBox.Show(fileContents)
    
    MessageBox.Show(fileContents);
    
  12. In the Build menu, click Build WPFCaching to build your project.

Testing Caching in the WPF Application

You can now test the application.

To test caching in the WPF application

  1. Press CTRL+F5 to run the application.

    The MainWindow window is displayed.

  2. Click Get Cache.

    The cached content from the text file is displayed in a message box. Notice the timestamp on the file.

  3. Close the message box and then click Get Cache again**.**

    The timestamp is unchanged. This indicates the cached content is displayed.

  4. Wait 10 seconds or more and then click Get Cache again.

    This time a new timestamp is displayed. This indicates that the policy let the cache entry expire and that new cached content is displayed.

  5. In a text editor, open the text file that you created. Do not make any changes yet.

  6. Close the message box and then click Get Cache again**.**

    Notice the timestamp again.

  7. Make a change to the text file and then save the file.

  8. Close the message box and then click Get Cache again.

    This message box contains the updated content from the text file and a new timestamp. This indicates that the host-file change monitor evicted the cache entry immediately when you changed the file, even though the absolute timeout period had not expired.

    Note

    You can increase the eviction time to 20 seconds or more to allow more time for you to make a change in the file.

Code Example

After you have completed this walkthrough, the code for the project you created will resemble the following example.

Imports System.Runtime.Caching
Imports System.IO

Class MainWindow

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
        Dim cache As ObjectCache = MemoryCache.Default
        Dim fileContents As String = TryCast(cache("filecontents"), _
            String)

        If fileContents Is Nothing Then
            Dim policy As New CacheItemPolicy()
            policy.AbsoluteExpiration = _
                DateTimeOffset.Now.AddSeconds(10.0)
            Dim filePaths As New List(Of String)()
            filePaths.Add("c:\cache\cacheText.txt")
            policy.ChangeMonitors.Add(New  _
                HostFileChangeMonitor(filePaths))

            ' Fetch the file contents.
            fileContents = File.ReadAllText("c:\cache\cacheText.txt") & vbCrLf & DateTime.Now.ToString()
            cache.Set("filecontents", fileContents, policy)
        End If
        MessageBox.Show(fileContents)
    End Sub
End Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.Caching;
using System.IO;


namespace WPFCaching
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {

            ObjectCache cache = MemoryCache.Default;
            string fileContents = cache["filecontents"] as string;

            if (fileContents == null)
            {
                CacheItemPolicy policy = new CacheItemPolicy();
                policy.AbsoluteExpiration =
                    DateTimeOffset.Now.AddSeconds(10.0);

                List<string> filePaths = new List<string>();
                filePaths.Add("c:\\cache\\cacheText.txt");

                policy.ChangeMonitors.Add(new
                    HostFileChangeMonitor(filePaths));

                // Fetch the file contents.
                fileContents = File.ReadAllText("c:\\cache\\cacheText.txt") + "\n" + DateTime.Now.ToString();

                cache.Set("filecontents", fileContents, policy);

            }
            MessageBox.Show(fileContents);


        }
    }
}

See Also

Reference

MemoryCache

ObjectCache

System.Runtime.Caching

Concepts

Caching in .NET Framework Applications