演练:在 WPF 应用程序中缓存应用程序数据
03/30/2017
本文内容
缓存可以将数据存储在内存中以便快速访问。 再次访问数据时,应用程序可以从缓存获取数据,而不是从原始源检索数据。 这可改善性能和可伸缩性。 此外,数据源暂时不可用时,缓存可提供数据。
.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 将创建 " 我的项目 " 文件夹、应用程序 .xaml 文件和 mainwindow.xaml 文件。
针对 .NET Framework 并添加对缓存程序集的引用
默认情况下,WPF 应用程序以 .NET Framework 4 客户端配置文件为目标。 若要 System.Runtime.Caching 在 WPF 应用程序中使用命名空间,应用程序必须以 .NET Framework 4 (而不是 .NET Framework 4 客户端配置) 文件为目标,并且必须包括对命名空间的引用。
因此,下一步是更改 .NET Framework 目标并添加对 System.Runtime.Caching 命名空间的引用。
备注
更改 .NET Framework 目标的过程在 Visual Basic 项目和 Visual c # 项目中是不同的。
更改目标 .NET Framework Visual Basic
在 " 解决方案资源管理器" 中,右键单击项目名称,然后单击 " 属性"。
将显示应用程序的 "属性" 窗口。
单击“编译” 选项卡。
在窗口底部,单击 " 高级编译选项 ..."。
将显示 " 高级编译器设置 " 对话框。
在 " 目标框架 (" 所有配置 ") 列表中,选择" .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 窗口。
在 " 属性 " 窗口中,将 Content 控件的属性设置为 " Button 获取缓存"。
初始化缓存并缓存项
接下来,你将添加代码来执行以下任务:
创建缓存类的实例,即,将实例化一个新的 MemoryCache 对象。
读取文本文件并将其内容缓存为缓存条目。
显示缓存的文本文件的内容。
创建缓存对象
双击您刚添加的按钮,以便在 Mainwindow.xaml 或 Mainwindow.xaml 文件中创建事件处理程序,。
在类声明) 之前 (文件顶部,添加以下 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 filePaths = new List();
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
{
///
/// Interaction logic for MainWindow.xaml
///
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 filePaths = new List();
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
另请参阅