演练:在 WPF 应用程序中缓存应用程序数据
通过缓存,可以将数据存储在内存中以便快速访问。 再次访问数据时,应用程序可以从缓存中获取数据,而不是从原始源检索数据。 这可以提高性能和可伸缩性。 此外,缓存使数据在数据源暂时不可用时可用。
.NET Framework 提供了可用于在 .NET Framework 应用程序中使用缓存的类。 这些类位于 System.Runtime.Caching 命名空间中。
注意
System.Runtime.Caching 命名空间在 .NET Framework 4 中是新的。 此命名空间使缓存适用于所有 .NET Framework 应用程序。 在 .NET Framework 的早期版本中,缓存仅在 System.Web 命名空间中可用,因此需要依赖 ASP.NET 类。
本演练演示如何使用 .NET Framework 中提供的缓存功能作为 Windows Presentation Foundation (WPF) 应用程序的一部分。 在演练中,您缓存一个文本文件中的内容。
本演练中演示的任务包括:
创建 WPF 应用程序项目。
添加对 .NET Framework 4 的引用。
初始化缓存。
添加包含文本文件内容的缓存项。
为缓存项提供逐出策略。
监视缓存文件的路径,并通知缓存实例对受监视项的更改。
先决条件
为了完成这一演练,您将需要:
Visual Studio 2010。
包含少量文本的文本文件。 (将在消息框中显示文本文件的内容。演练中演示的代码假定你正在处理以下文件:
c:\cache\cacheText.txt
但是,可以使用任何文本文件,对本演练中的代码进行少量更改。
创建 WPF 应用程序项目
首先创建 WPF 应用程序项目。
创建 WPF 应用程序
启动 Visual Studio。
在“文件”菜单中,单击 “新建”,然后单击 “新建项目”。
“新建项目 ”对话框 被显示。
在 已安装的模板下,选择要使用的编程语言(Visual Basic 或 Visual C#)。
在 “新建项目”对话框中,选择 WPF 应用程序。
注意
如果未看到 WPF 应用程序 模板,请确保目标支持 WPF 的 .NET Framework 版本。 在“新建项目 对话框中,从列表中选择 .NET Framework 4。
在 名称 文本框中,输入项目的名称。 例如,可以输入 WPFCaching。
选中“为解决方案 创建目录”复选框
。 单击“确定”。
WPF 设计器将在 设计 视图中打开,并显示 MainWindow.xaml 文件。 Visual Studio 创建 “我的项目” 文件夹、Application.xaml 文件和 MainWindow.xaml 文件。
面向 .NET Framework 并添加对缓存程序集的引用
默认情况下,WPF 应用程序面向 .NET Framework 4 客户端配置。 若要在 WPF 应用程序中使用 System.Runtime.Caching 命名空间,应用程序必须面向 .NET Framework 4(而不是 .NET Framework 4 客户端配置文件),并且必须包含对命名空间的引用。
因此,下一步是更改 .NET Framework 目标并添加对 System.Runtime.Caching 命名空间的引用。
注意
更改 .NET Framework 目标的过程在 Visual Basic 项目和 Visual C# 项目中是不同的。
在 Visual Basic 中更改目标 .NET Framework
在 解决方案资源管理器中,右键单击项目名称,然后单击 属性。
将显示应用程序的属性窗口。
单击“编译”选项卡。
在窗口底部,单击“高级编译选项...”。
将显示 高级编译器设置 对话框。
在 目标框架(所有配置) 列表中,选择 .NET Framework 4。 (请勿选择 .NET Framework 4 客户端配置文件。)
单击“确定”。
目标框架更改 对话框将显示。
在 目标框架更改 对话框中,单击 是。
项目已关闭,之后重新打开。
按照以下步骤添加对缓存程序集的引用:
在 解决方案资源管理器中,右键单击项目的名称,然后单击 添加引用。
选择 .NET 选项卡,选择
System.Runtime.Caching
,然后单击 确定。
更改 Visual C# 项目中的目标 .NET Framework
在 解决方案资源管理器中,右键单击项目名称,然后单击 属性。
将显示应用程序的属性窗口。
单击 应用程序 选项卡。
在 目标框架 列表中,选择 .NET Framework 4。 (请勿选择 .NET Framework 4 客户端配置文件。)
按照以下步骤添加对缓存程序集的引用:
右键单击 引用 文件夹,然后单击 添加引用。
选择 .NET 选项卡,选择
System.Runtime.Caching
,然后单击 确定。
向 WPF 窗口添加按钮
接下来,添加按钮控件并为按钮的 Click
事件创建事件处理程序。 稍后将添加代码,以便在单击按钮时缓存并显示文本文件的内容。
添加按钮控件
在 解决方案资源管理器中,双击 MainWindow.xaml 文件将其打开。
在“工具箱”的 “公共 WPF 控件”下,将
Button
控件拖到MainWindow
窗口中。在 属性 窗口中,将
Button
控件的Content
属性设置为 获取缓存。
初始化缓存和缓存一个条目
接下来,添加代码以执行以下任务:
创建缓存类的实例,即实例化新的 MemoryCache 对象。
指定缓存使用 HostFileChangeMonitor 对象监视文本文件中的更改。
读取文本文件并将其内容缓存为缓存条目。
显示缓存文本文件的内容。
创建缓存对象
双击刚添加的按钮,以便在MainWindow.xaml.cs或MainWindow.Xaml.vb文件中创建事件处理程序。
在文件顶部(类声明之前),添加以下
Imports
(Visual Basic)或using
(C#) 语句:using System.Runtime.Caching; using System.IO;
Imports System.Runtime.Caching Imports System.IO
在事件处理程序中,添加以下代码来实例化缓存对象:
ObjectCache cache = MemoryCache.Default;
Dim cache As ObjectCache = MemoryCache.Default
ObjectCache 类是提供内存中对象缓存的内置类。
添加以下代码以读取名为
filecontents
的缓存项的内容:Dim fileContents As String = TryCast(cache("filecontents"), String)
string fileContents = cache["filecontents"] as string;
添加以下代码以检查名为
filecontents
的缓存项是否存在:If fileContents Is Nothing Then End If
if (fileContents == null) { }
如果指定的缓存项不存在,则必须读取文本文件并将其作为缓存项添加到缓存中。
在
if/then
块中,添加以下代码以创建一个新的 CacheItemPolicy 对象,该对象指定缓存项在 10 秒后过期。Dim policy As New CacheItemPolicy() policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10.0)
CacheItemPolicy policy = new CacheItemPolicy(); policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10.0);
如果未提供逐出或过期信息,则默认值为 InfiniteAbsoluteExpiration,这意味着缓存条目永远不会基于绝对时间过期。 而缓存条目仅在存在内存压力时过期。 最佳做法是,应始终显式提供绝对或滑动过期时间。
在
if/then
块中,按照在上一步中添加的代码,添加以下代码,为要监视的文件路径创建集合,并将文本文件的路径添加到集合: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");
注意
如果您要使用的文本文件不是
c:\cache\cacheText.txt
,请指定该文本文件所在的路径。按照在上一步中添加的代码,添加以下代码,将新的 HostFileChangeMonitor 对象添加到缓存项的更改监视器集合中:
policy.ChangeMonitors.Add(New HostFileChangeMonitor(filePaths))
policy.ChangeMonitors.Add(new HostFileChangeMonitor(filePaths));
HostFileChangeMonitor 对象监视文本文件的路径,并在发生更改时通知缓存。 在此示例中,如果文件的内容发生更改,缓存项将过期。
按照在上一步中添加的代码,添加以下代码以读取文本文件的内容:
fileContents = File.ReadAllText("c:\cache\cacheText.txt") & vbCrLf & DateTime.Now.ToString()
fileContents = File.ReadAllText("c:\\cache\\cacheText.txt") + "\n" + DateTime.Now;
添加日期和时间时间戳,以便你能够查看缓存条目何时过期。
按照在上一步中添加的代码,添加以下代码,以将文件的内容作为 CacheItem 实例插入缓存对象:
cache.Set("filecontents", fileContents, policy)
cache.Set("filecontents", fileContents, policy);
通过将之前创建的 CacheItemPolicy 对象作为参数传递,你可以指定关于如何逐出缓存项的信息。
在
if/then
块之后,添加以下代码以在消息框中显示缓存的文件内容:MessageBox.Show(fileContents)
MessageBox.Show(fileContents);
在 构建 菜单中,单击 构建 WPFCaching 以构建项目。
在 WPF 应用程序中测试缓存
现在可以测试应用程序。
在 WPF 应用程序中测试缓存
按 Ctrl+F5 运行应用程序。
MainWindow
窗口已显示。单击 获取缓存。
文本文件中的缓存内容显示在消息框中。 请注意文件的时间戳。
关闭消息框,然后再次单击 “获取缓存”。
时间戳不变。 这表示显示缓存的内容。
等待 10 秒或更多时间,然后单击 再次获取缓存。
此时会显示新的时间戳。 这表示策略允许缓存项过期,并显示新的缓存内容。
在文本编辑器中,打开创建的文本文件。 暂时不要做任何更改。
关闭消息框,然后再次单击 获取缓存。
再次注意时间戳。
对文本文件进行更改,然后保存该文件。
关闭消息框,然后再次单击 获取缓存。
此消息框包含文本文件中的更新内容和新时间戳。 这表示主机文件更改监视器在您更改文件时立即将缓存条目移除,即使绝对超时时间尚未到期。
注意
可以将逐出时间增加到 20 秒或更多,以便你有更多的时间在文件中进行更改。
代码示例
完成本演练后,所创建项目的代码将类似于以下示例。
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);
}
}
}
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
另请参阅
- MemoryCache
- ObjectCache
- System.Runtime.Caching
- .NET Framework 应用程序中的 缓存