(.Net) 使用内存映射文件的简单方法。就像一个变量
(.Net) Easy way to use Memory Mapped Files. Just like a variable
我正在开发 ASP.NET 网络应用程序。它需要大量的内存。因此,我正在考虑内存映射文件。
但是,实现内存映射文件非常累人。它需要使用那些内存地址、SizeOf 运算符等。(我 运行 没时间了)。
当前系统使用大字典来存储大量数据。所有 类 都是 [Serializable]。 有没有办法像这样结束对内存映射文件的访问,
(C# Psedo-code)
var WrittingObject = new blablabla;
SetMMFVariable(name: "var1", value : WrittingObject);
var ReadingObject = GetMMFVariable(name: "var1");
.NET 中是否有内存映射文件的包装代码?我不必担心那些内存地址和其他东西。
这将是一个很好的数据库候选者!您遇到的问题是一次 serializing/deserializing 大量信息。如果您需要读取或更新一小段信息,则需要扫描整个文件以更新单个记录。这太贵了!
解决方法是使用一些结构化数据模型。您可以分发模型 read/writes 以使用 OS 上的许多小文件(可能会损坏、磁盘问题、权限问题、多重访问和文件锁定)来解决上述序列化问题,或者您可以转到一个实际的数据库,它将允许您查询 & update/insert 您需要的信息。
对于结构化模型(c# 擅长此),请查看 Sql Server Express
https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/sql-server-express-localdb?view=sql-server-2017
对于非结构化信息 (json) 查看非关系型信息,例如 couchbase
https://docs.couchbase.com/dotnet-sdk/2.7/start-using-sdk.html
我做了一个解决方案。
这是一个有点乱的代码。它与项目的其他部分有关。但是你可以让它很容易携带。
(Visual Basic .NET 代码)
Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Web.UI
Public Module UserStates
Public Property CurrSessionVariableIndex As Integer
Get
Dim I As Integer
If LDB.CustomData.TryGetValue("CurrSessionIndex", I) Then
Return I
Else
LDB.CustomData("CurrSessionIndex") = 1
Return I
End If
End Get
Set(value As Integer)
LDB.CustomData("CurrSessionIndex") = value
End Set
End Property
Public Function NewSessionVariableIndex() As Integer
CurrSessionVariableIndex += 1
Return CurrSessionVariableIndex
End Function
Public PreferMemoryMapFiles As Boolean = True
Public ViewStatusBags As New Dictionary(Of Integer, Dictionary(Of String, Object))(300)
Public ViewStatusTimes As New Dictionary(Of Integer, DateTime)(300)
Public Sub SetViewVarRAM(ViewStateID As Integer, key As String, Obj As Object)
Dim Bag As Dictionary(Of String, Object) = Nothing
If ViewStatusBags.TryGetValue(ViewStateID, Bag) Then
Try
Bag(key) = Obj
Catch ex As Exception
Log($"Added new ViewBag.Var {ViewStateID}.{key}")
Bag.Add(key, Obj)
End Try
ViewStatusTimes(ViewStateID) = Now
Else
Log($"Added new ViewBag {ViewStateID}")
Bag = New Dictionary(Of String, Object)
ViewStatusBags.Add(ViewStateID, Bag)
ViewStatusTimes.Add(ViewStateID, Now)
Bag.Add(key, Obj)
End If
End Sub
Public Function GetViewVarRAM(ViewStateID As Integer, key As String) As Object
Dim Bag As Dictionary(Of String, Object) = Nothing
If ViewStatusBags.TryGetValue(ViewStateID, Bag) Then
ViewStatusTimes(ViewStateID) = Now
Try
Return Bag(key)
Catch ex As Exception
Log($"Added new ViewBag.Var {ViewStateID}.{key}")
Bag.Add(key, Nothing)
Return Bag(key)
End Try
Else
Log($"Added new ViewBag {ViewStateID}")
Bag = New Dictionary(Of String, Object)
ViewStatusBags.Add(ViewStateID, Bag)
ViewStatusTimes.Add(ViewStateID, Now)
Bag.Add(key, Nothing)
Return Bag(key)
End If
End Function
Public Function GetViewMMF(ViewStateID As Integer) As Dictionary(Of String, Object)
Dim FS As FileStream = Nothing
Dim BF As New BinaryFormatter
GetFileStream(ViewStateID, FS)
Dim Bag As Dictionary(Of String, Object)
Try
Bag = BF.Deserialize(FS)
Catch ex As Exception
If Not ex.Message.StartsWith("Attempting to deserialize an empty stream") Then
LogError(ex, $"@MMF.Get : cannot Deserialize FS {ViewStateID}")
End If
FS.Flush()
Bag = New Dictionary(Of String, Object)
SetViewMMF(ViewStateID, Bag)
End Try
Try
FS.Flush()
Catch ex As Exception
End Try
Return Bag
End Function
Public Sub SetViewMMF(ViewStateID As Integer, Bag As Dictionary(Of String, Object))
Dim FS As FileStream = Nothing
Dim BF As New BinaryFormatter
GetFileStream(ViewStateID, FS)
Try
BF.Serialize(FS, Bag)
Catch ex As Exception
LogError(ex, $"@MMF.Set : cannot Serialize FS {ViewStateID}")
FS.Flush()
End Try
Try
FS.Flush()
Catch ex As Exception
End Try
End Sub
Public MMFStreams As New Dictionary(Of Integer, FileStream)(100)
Public MMFStreamsTimes As New Dictionary(Of Integer, Date)(100)
Public FilePathMMFs As String
Private Sub GetFileStream(ByRef ViewStateID As Integer, ByRef FS As FileStream)
If MMFStreams.TryGetValue(ViewStateID, FS) Then
Try
FS.Seek(0, SeekOrigin.Begin)
Catch ex As Exception
LogError(ex, $"@MMF.Set : cannot restart FS {ViewStateID}")
FS = New FileStream(FilePathMMFs & ViewStateID.ToString & "-" & Rand.Next(100, 1000).ToString, FileMode.OpenOrCreate)
FS.Seek(0, SeekOrigin.Begin)
MMFStreams(ViewStateID) = FS
End Try
MMFStreamsTimes(ViewStateID) = Now
Else
Try
FS = New FileStream(FilePathMMFs & ViewStateID.ToString, FileMode.OpenOrCreate)
FS.Seek(0, SeekOrigin.Begin)
MMFStreams.Add(ViewStateID, FS)
Catch ex As Exception
LogError(ex, $"@MMF.Set : cannot OpenOrCreate new FS {ViewStateID}")
FS = New FileStream(FilePathMMFs & ViewStateID.ToString & "-" & Rand.Next(100, 1000).ToString, FileMode.OpenOrCreate)
FS.Seek(0, SeekOrigin.Begin)
MMFStreams.Add(ViewStateID, FS)
End Try
MMFStreamsTimes(ViewStateID) = Now
End If
End Sub
Public Sub SetViewVarMMF(ViewStateID As Integer, key As String, Obj As Object)
Dim FS As FileStream = Nothing
Dim BF As New BinaryFormatter
GetFileStream(ViewStateID, FS)
Dim Bag As Dictionary(Of String, Object)
Try
Bag = BF.Deserialize(FS)
Catch ex As Exception
'LogError(ex, $"@MMF.SetViewVarMMF : cannot Deserialize FS {ViewStateID}. saved new bag")
Bag = New Dictionary(Of String, Object)
End Try
FS.Seek(0, SeekOrigin.Begin)
If Bag.ContainsKey(key) Then
Bag(key) = Obj
Else
Bag.Add(key, Obj)
End If
Try
BF.Serialize(FS, Bag)
Catch ex As Exception
LogError(ex, $"@MMF.SetViewVarMMF : cannot Serialize FS {ViewStateID}")
FS.Flush()
End Try
Try
FS.Flush()
Catch ex As Exception
End Try
End Sub
Public Function GetViewVarMMF(ViewStateID As Integer, key As String) As Object
Dim Bag = GetViewMMF(ViewStateID)
Dim Obj As Object = Nothing
If Bag.TryGetValue(key, Obj) Then
Return Obj
Else
Return Nothing
End If
Bag = Nothing
End Function
Public AllUserContainer As New Dictionary(Of Integer, UserContainer)(50)
Public Sub SetUserContainer(Usr As Integer, Con As UserContainer)
Con.UserID = Usr
If AllUserContainer.ContainsKey(Usr) Then
AllUserContainer(Usr) = Con
Con.Time = Now
Else
Log($"Added new user {Usr}")
AllUserContainer.Add(Usr, Con)
Con.Time = Now
End If
End Sub
Public Function GetUserContainer(Usr As Integer) As UserContainer
Dim Con As UserContainer = Nothing
If AllUserContainer.TryGetValue(Usr, Con) Then
Con.Time = Now
Return Con
Else
Log($"Added new user {Usr}")
Con = New UserContainer(Usr)
AllUserContainer.Add(Usr, Con)
Con.Time = Now
Return Con
End If
End Function
'___________________________________________________'
Public Sub SetViewVar(ViewStateID As Integer, key As String, Obj As Object)
If PreferMemoryMapFiles Then
SetViewVarMMF(ViewStateID, key, Obj)
Else
SetViewVarRAM(ViewStateID, key, Obj)
End If
End Sub
Public Function GetViewVar(ViewStateID As Integer, key As String) As Object
If PreferMemoryMapFiles Then
Return GetViewVarMMF(ViewStateID, key)
Else
Return GetViewVarRAM(ViewStateID, key)
End If
End Function
Public Sub RemoveMMF(ViewStateID As Integer)
Dim FS As FileStream = Nothing
If MMFStreams.TryGetValue(ViewStateID, FS) Then
Try
FS.Close()
Catch ex As Exception
End Try
End If
End Sub
Public Sub RemoveUserContainer(Usr As Integer)
If AllUserContainer.ContainsKey(Usr) Then
AllUserContainer(Usr).Dispose()
AllUserContainer.Remove(Usr)
Log($"Removed user {Usr}")
End If
End Sub
Public Sub DeleteUnusedMMFs()
Dim Files = Directory.GetFiles(FilePathMMFs)
Dim nowTime As Date = Now
Dim nOfFiles = 0I
For Each FilePath In Files
Dim FileID = Path.GetFileName(FilePath)
Dim Time As Date = Date.MinValue
If UserStates.MMFStreamsTimes.TryGetValue(FileID, Time) Then
If Time.AddMinutes(5) < nowTime Then
Try
UserStates.MMFStreams(FileID).Close()
Catch ex As Exception
End Try
Try
File.Delete(FilePath)
nOfFiles += 1
Catch ex As Exception
End Try
End If
Else
Try
File.Delete(FilePath)
nOfFiles += 1
Catch ex As Exception
End Try
End If
Next
Log($"@ViewStates.DeleteUnusedMMFs : {nOfFiles} deleted")
End Sub
'___________________________________________________'
Public Sub ClearUnusedViewStates()
Dim BeforeRAM = (My.Application.Info.WorkingSet / 1024) / 1024
Dim CurrTime = Now
Dim ToRemove As New List(Of Integer)
Dim ViewEntries As Integer
Dim UsrEntries As Integer
If ViewStatusBags.Count = 0 Then
GoTo RemoveusrsLbl
End If
For i = ViewStatusBags.Count - 1 To 0 Step -1
Dim Time = ViewStatusTimes.ElementAt(i).Value
If Time.AddMinutes(5) < CurrTime Then
ToRemove.Add(ViewStatusBags.ElementAt(i).Key)
End If
Next
ViewEntries = ToRemove.Count
For Each i In ToRemove
ViewStatusBags.Remove(i)
Next
RemoveusrsLbl:
If AllUserContainer.Count = 0 Then
GoTo Final
End If
For i = AllUserContainer.Count - 1 To 0 Step -1
If AllUserContainer(i).Time.AddMinutes(15) < CurrTime Then
AllUserContainer.Remove(AllUserContainer(i).UserID)
UsrEntries += 1
End If
Next
Final:
GC.Collect()
Dim AfterRAM = (My.Application.Info.WorkingSet / 1024) / 1024
Log($"@ViewStates : {ViewEntries} Unused ViewStates Cleared. {UsrEntries} inactive users cleared. {AfterRAM - BeforeRAM} MB Cleared. ")
End Sub
End Module
(C# 代码)(已翻译)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualBasic;
using System.Runtime.Serialization.Formatters.Binary;
using System.Web.UI;
public static class UserStates
{
public static int CurrSessionVariableIndex
{
get
{
int I;
if (LDB.CustomData.TryGetValue("CurrSessionIndex", I))
return I;
else
{
LDB.CustomData("CurrSessionIndex") = 1;
return I;
}
}
set
{
LDB.CustomData("CurrSessionIndex") = value;
}
}
public static int NewSessionVariableIndex()
{
CurrSessionVariableIndex += 1;
return CurrSessionVariableIndex;
}
public static bool PreferMemoryMapFiles = true;
public static Dictionary<int, Dictionary<string, object>> ViewStatusBags = new Dictionary<int, Dictionary<string, object>>(300);
public static Dictionary<int, DateTime> ViewStatusTimes = new Dictionary<int, DateTime>(300);
public static void SetViewVarRAM(int ViewStateID, string key, object Obj)
{
Dictionary<string, object> Bag = null;
if (ViewStatusBags.TryGetValue(ViewStateID, out Bag))
{
try
{
Bag[key] = Obj;
}
catch (Exception ex)
{
Log($"Added new ViewBag.Var {ViewStateID}.{key}");
Bag.Add(key, Obj);
}
ViewStatusTimes[ViewStateID] = DateTime.Now;
}
else
{
Log($"Added new ViewBag {ViewStateID}");
Bag = new Dictionary<string, object>();
ViewStatusBags.Add(ViewStateID, Bag);
ViewStatusTimes.Add(ViewStateID, DateTime.Now);
Bag.Add(key, Obj);
}
}
public static object GetViewVarRAM(int ViewStateID, string key)
{
Dictionary<string, object> Bag = null;
if (ViewStatusBags.TryGetValue(ViewStateID, out Bag))
{
ViewStatusTimes[ViewStateID] = DateTime.Now;
try
{
return Bag[key];
}
catch (Exception ex)
{
Log($"Added new ViewBag.Var {ViewStateID}.{key}");
Bag.Add(key, null);
return Bag[key];
}
}
else
{
Log($"Added new ViewBag {ViewStateID}");
Bag = new Dictionary<string, object>();
ViewStatusBags.Add(ViewStateID, Bag);
ViewStatusTimes.Add(ViewStateID, DateTime.Now);
Bag.Add(key, null);
return Bag[key];
}
}
public static Dictionary<string, object> GetViewMMF(int ViewStateID)
{
FileStream FS = null;
BinaryFormatter BF = new BinaryFormatter();
GetFileStream(ref ViewStateID, ref FS);
Dictionary<string, object> Bag;
try
{
Bag = BF.Deserialize(FS);
}
catch (Exception ex)
{
if (!ex.Message.StartsWith("Attempting to deserialize an empty stream"))
LogError(ex, $"@MMF.Get : cannot Deserialize FS {ViewStateID}");
FS.Flush();
Bag = new Dictionary<string, object>();
SetViewMMF(ViewStateID, Bag);
}
try
{
FS.Flush();
}
catch (Exception ex)
{
}
return Bag;
}
public static void SetViewMMF(int ViewStateID, Dictionary<string, object> Bag)
{
FileStream FS = null;
BinaryFormatter BF = new BinaryFormatter();
GetFileStream(ref ViewStateID, ref FS);
try
{
BF.Serialize(FS, Bag);
}
catch (Exception ex)
{
LogError(ex, $"@MMF.Set : cannot Serialize FS {ViewStateID}");
FS.Flush();
}
try
{
FS.Flush();
}
catch (Exception ex)
{
}
}
public static Dictionary<int, FileStream> MMFStreams = new Dictionary<int, FileStream>(100);
public static Dictionary<int, DateTime> MMFStreamsTimes = new Dictionary<int, DateTime>(100);
public static string FilePathMMFs;
private static void GetFileStream(ref int ViewStateID, ref FileStream FS)
{
if (MMFStreams.TryGetValue(ViewStateID, out FS))
{
try
{
FS.Seek(0, SeekOrigin.Begin);
}
catch (Exception ex)
{
LogError(ex, $"@MMF.Set : cannot restart FS {ViewStateID}");
FS = new FileStream(FilePathMMFs + ViewStateID.ToString() + "-" + Rand.Next(100, 1000).ToString, FileMode.OpenOrCreate);
FS.Seek(0, SeekOrigin.Begin);
MMFStreams[ViewStateID] = FS;
}
MMFStreamsTimes[ViewStateID] = DateTime.Now;
}
else
{
try
{
FS = new FileStream(FilePathMMFs + ViewStateID.ToString(), FileMode.OpenOrCreate);
FS.Seek(0, SeekOrigin.Begin);
MMFStreams.Add(ViewStateID, FS);
}
catch (Exception ex)
{
LogError(ex, $"@MMF.Set : cannot OpenOrCreate new FS {ViewStateID}");
FS = new FileStream(FilePathMMFs + ViewStateID.ToString() + "-" + Rand.Next(100, 1000).ToString, FileMode.OpenOrCreate);
FS.Seek(0, SeekOrigin.Begin);
MMFStreams.Add(ViewStateID, FS);
}
MMFStreamsTimes[ViewStateID] = DateTime.Now;
}
}
public static void SetViewVarMMF(int ViewStateID, string key, object Obj)
{
FileStream FS = null;
BinaryFormatter BF = new BinaryFormatter();
GetFileStream(ref ViewStateID, ref FS);
Dictionary<string, object> Bag;
try
{
Bag = BF.Deserialize(FS);
}
catch (Exception ex)
{
// LogError(ex, $"@MMF.SetViewVarMMF : cannot Deserialize FS {ViewStateID}. saved new bag")
Bag = new Dictionary<string, object>();
}
FS.Seek(0, SeekOrigin.Begin);
if (Bag.ContainsKey(key))
Bag[key] = Obj;
else
Bag.Add(key, Obj);
try
{
BF.Serialize(FS, Bag);
}
catch (Exception ex)
{
LogError(ex, $"@MMF.SetViewVarMMF : cannot Serialize FS {ViewStateID}");
FS.Flush();
}
try
{
FS.Flush();
}
catch (Exception ex)
{
}
}
public static object GetViewVarMMF(int ViewStateID, string key)
{
var Bag = GetViewMMF(ViewStateID);
object Obj = null;
if (Bag.TryGetValue(key, out Obj))
return Obj;
else
return null;
Bag = null;
}
public static Dictionary<int, UserContainer> AllUserContainer = new Dictionary<int, UserContainer>(50);
public static void SetUserContainer(int Usr, UserContainer Con)
{
Con.UserID = Usr;
if (AllUserContainer.ContainsKey(Usr))
{
AllUserContainer[Usr] = Con;
Con.Time = DateTime.Now;
}
else
{
Log($"Added new user {Usr}");
AllUserContainer.Add(Usr, Con);
Con.Time = DateTime.Now;
}
}
public static UserContainer GetUserContainer(int Usr)
{
UserContainer Con = null/* TODO Change to default(_) if this is not a reference type */;
if (AllUserContainer.TryGetValue(Usr, out Con))
{
Con.Time = DateTime.Now;
return Con;
}
else
{
Log($"Added new user {Usr}");
Con = new UserContainer(Usr);
AllUserContainer.Add(Usr, Con);
Con.Time = DateTime.Now;
return Con;
}
}
// ___________________________________________________'
public static void SetViewVar(int ViewStateID, string key, object Obj)
{
if (PreferMemoryMapFiles)
SetViewVarMMF(ViewStateID, key, Obj);
else
SetViewVarRAM(ViewStateID, key, Obj);
}
public static object GetViewVar(int ViewStateID, string key)
{
if (PreferMemoryMapFiles)
return GetViewVarMMF(ViewStateID, key);
else
return GetViewVarRAM(ViewStateID, key);
}
public static void RemoveMMF(int ViewStateID)
{
FileStream FS = null;
if (MMFStreams.TryGetValue(ViewStateID, out FS))
{
try
{
FS.Close();
}
catch (Exception ex)
{
}
}
}
public static void RemoveUserContainer(int Usr)
{
if (AllUserContainer.ContainsKey(Usr))
{
AllUserContainer[Usr].Dispose();
AllUserContainer.Remove(Usr);
Log($"Removed user {Usr}");
}
}
public static void DeleteUnusedMMFs()
{
var Files = Directory.GetFiles(FilePathMMFs);
DateTime nowTime = DateTime.Now;
var nOfFiles = 0;
foreach (var FilePath in Files)
{
var FileID = Path.GetFileName(FilePath);
DateTime Time = DateTime.MinValue;
if (UserStates.MMFStreamsTimes.TryGetValue(FileID, out Time))
{
if (Time.AddMinutes(5) < nowTime)
{
try
{
UserStates.MMFStreams[FileID].Close();
}
catch (Exception ex)
{
}
try
{
File.Delete(FilePath);
nOfFiles += 1;
}
catch (Exception ex)
{
}
}
}
else
try
{
File.Delete(FilePath);
nOfFiles += 1;
}
catch (Exception ex)
{
}
}
Log($"@ViewStates.DeleteUnusedMMFs : {nOfFiles} deleted");
}
// ___________________________________________________'
public static void ClearUnusedViewStates()
{
var BeforeRAM = (My.Application.Info.WorkingSet / (double)1024) / (double)1024;
var CurrTime = DateTime.Now;
List<int> ToRemove = new List<int>();
int ViewEntries;
int UsrEntries;
if (ViewStatusBags.Count == 0)
goto RemoveusrsLbl;
for (var i = ViewStatusBags.Count - 1; i >= 0; i += -1)
{
var Time = ViewStatusTimes.ElementAt(i).Value;
if (Time.AddMinutes(5) < CurrTime)
ToRemove.Add(ViewStatusBags.ElementAt(i).Key);
}
ViewEntries = ToRemove.Count;
foreach (var i in ToRemove)
ViewStatusBags.Remove(i);
RemoveusrsLbl:
;
if (AllUserContainer.Count == 0)
goto Final;
for (var i = AllUserContainer.Count - 1; i >= 0; i += -1)
{
if (AllUserContainer[i].Time.AddMinutes(15) < CurrTime)
{
AllUserContainer.Remove(AllUserContainer[i].UserID);
UsrEntries += 1;
}
}
Final:
;
GC.Collect();
var AfterRAM = (My.Application.Info.WorkingSet / (double)1024) / (double)1024;
Log($"@ViewStates : {ViewEntries} Unused ViewStates Cleared. {UsrEntries} inactive users cleared. {AfterRAM - BeforeRAM} MB Cleared. ");
}
}
我正在开发 ASP.NET 网络应用程序。它需要大量的内存。因此,我正在考虑内存映射文件。
但是,实现内存映射文件非常累人。它需要使用那些内存地址、SizeOf 运算符等。(我 运行 没时间了)。
当前系统使用大字典来存储大量数据。所有 类 都是 [Serializable]。 有没有办法像这样结束对内存映射文件的访问,
(C# Psedo-code)
var WrittingObject = new blablabla;
SetMMFVariable(name: "var1", value : WrittingObject);
var ReadingObject = GetMMFVariable(name: "var1");
.NET 中是否有内存映射文件的包装代码?我不必担心那些内存地址和其他东西。
这将是一个很好的数据库候选者!您遇到的问题是一次 serializing/deserializing 大量信息。如果您需要读取或更新一小段信息,则需要扫描整个文件以更新单个记录。这太贵了!
解决方法是使用一些结构化数据模型。您可以分发模型 read/writes 以使用 OS 上的许多小文件(可能会损坏、磁盘问题、权限问题、多重访问和文件锁定)来解决上述序列化问题,或者您可以转到一个实际的数据库,它将允许您查询 & update/insert 您需要的信息。
对于结构化模型(c# 擅长此),请查看 Sql Server Express https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/sql-server-express-localdb?view=sql-server-2017
对于非结构化信息 (json) 查看非关系型信息,例如 couchbase https://docs.couchbase.com/dotnet-sdk/2.7/start-using-sdk.html
我做了一个解决方案。 这是一个有点乱的代码。它与项目的其他部分有关。但是你可以让它很容易携带。
(Visual Basic .NET 代码)
Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Web.UI
Public Module UserStates
Public Property CurrSessionVariableIndex As Integer
Get
Dim I As Integer
If LDB.CustomData.TryGetValue("CurrSessionIndex", I) Then
Return I
Else
LDB.CustomData("CurrSessionIndex") = 1
Return I
End If
End Get
Set(value As Integer)
LDB.CustomData("CurrSessionIndex") = value
End Set
End Property
Public Function NewSessionVariableIndex() As Integer
CurrSessionVariableIndex += 1
Return CurrSessionVariableIndex
End Function
Public PreferMemoryMapFiles As Boolean = True
Public ViewStatusBags As New Dictionary(Of Integer, Dictionary(Of String, Object))(300)
Public ViewStatusTimes As New Dictionary(Of Integer, DateTime)(300)
Public Sub SetViewVarRAM(ViewStateID As Integer, key As String, Obj As Object)
Dim Bag As Dictionary(Of String, Object) = Nothing
If ViewStatusBags.TryGetValue(ViewStateID, Bag) Then
Try
Bag(key) = Obj
Catch ex As Exception
Log($"Added new ViewBag.Var {ViewStateID}.{key}")
Bag.Add(key, Obj)
End Try
ViewStatusTimes(ViewStateID) = Now
Else
Log($"Added new ViewBag {ViewStateID}")
Bag = New Dictionary(Of String, Object)
ViewStatusBags.Add(ViewStateID, Bag)
ViewStatusTimes.Add(ViewStateID, Now)
Bag.Add(key, Obj)
End If
End Sub
Public Function GetViewVarRAM(ViewStateID As Integer, key As String) As Object
Dim Bag As Dictionary(Of String, Object) = Nothing
If ViewStatusBags.TryGetValue(ViewStateID, Bag) Then
ViewStatusTimes(ViewStateID) = Now
Try
Return Bag(key)
Catch ex As Exception
Log($"Added new ViewBag.Var {ViewStateID}.{key}")
Bag.Add(key, Nothing)
Return Bag(key)
End Try
Else
Log($"Added new ViewBag {ViewStateID}")
Bag = New Dictionary(Of String, Object)
ViewStatusBags.Add(ViewStateID, Bag)
ViewStatusTimes.Add(ViewStateID, Now)
Bag.Add(key, Nothing)
Return Bag(key)
End If
End Function
Public Function GetViewMMF(ViewStateID As Integer) As Dictionary(Of String, Object)
Dim FS As FileStream = Nothing
Dim BF As New BinaryFormatter
GetFileStream(ViewStateID, FS)
Dim Bag As Dictionary(Of String, Object)
Try
Bag = BF.Deserialize(FS)
Catch ex As Exception
If Not ex.Message.StartsWith("Attempting to deserialize an empty stream") Then
LogError(ex, $"@MMF.Get : cannot Deserialize FS {ViewStateID}")
End If
FS.Flush()
Bag = New Dictionary(Of String, Object)
SetViewMMF(ViewStateID, Bag)
End Try
Try
FS.Flush()
Catch ex As Exception
End Try
Return Bag
End Function
Public Sub SetViewMMF(ViewStateID As Integer, Bag As Dictionary(Of String, Object))
Dim FS As FileStream = Nothing
Dim BF As New BinaryFormatter
GetFileStream(ViewStateID, FS)
Try
BF.Serialize(FS, Bag)
Catch ex As Exception
LogError(ex, $"@MMF.Set : cannot Serialize FS {ViewStateID}")
FS.Flush()
End Try
Try
FS.Flush()
Catch ex As Exception
End Try
End Sub
Public MMFStreams As New Dictionary(Of Integer, FileStream)(100)
Public MMFStreamsTimes As New Dictionary(Of Integer, Date)(100)
Public FilePathMMFs As String
Private Sub GetFileStream(ByRef ViewStateID As Integer, ByRef FS As FileStream)
If MMFStreams.TryGetValue(ViewStateID, FS) Then
Try
FS.Seek(0, SeekOrigin.Begin)
Catch ex As Exception
LogError(ex, $"@MMF.Set : cannot restart FS {ViewStateID}")
FS = New FileStream(FilePathMMFs & ViewStateID.ToString & "-" & Rand.Next(100, 1000).ToString, FileMode.OpenOrCreate)
FS.Seek(0, SeekOrigin.Begin)
MMFStreams(ViewStateID) = FS
End Try
MMFStreamsTimes(ViewStateID) = Now
Else
Try
FS = New FileStream(FilePathMMFs & ViewStateID.ToString, FileMode.OpenOrCreate)
FS.Seek(0, SeekOrigin.Begin)
MMFStreams.Add(ViewStateID, FS)
Catch ex As Exception
LogError(ex, $"@MMF.Set : cannot OpenOrCreate new FS {ViewStateID}")
FS = New FileStream(FilePathMMFs & ViewStateID.ToString & "-" & Rand.Next(100, 1000).ToString, FileMode.OpenOrCreate)
FS.Seek(0, SeekOrigin.Begin)
MMFStreams.Add(ViewStateID, FS)
End Try
MMFStreamsTimes(ViewStateID) = Now
End If
End Sub
Public Sub SetViewVarMMF(ViewStateID As Integer, key As String, Obj As Object)
Dim FS As FileStream = Nothing
Dim BF As New BinaryFormatter
GetFileStream(ViewStateID, FS)
Dim Bag As Dictionary(Of String, Object)
Try
Bag = BF.Deserialize(FS)
Catch ex As Exception
'LogError(ex, $"@MMF.SetViewVarMMF : cannot Deserialize FS {ViewStateID}. saved new bag")
Bag = New Dictionary(Of String, Object)
End Try
FS.Seek(0, SeekOrigin.Begin)
If Bag.ContainsKey(key) Then
Bag(key) = Obj
Else
Bag.Add(key, Obj)
End If
Try
BF.Serialize(FS, Bag)
Catch ex As Exception
LogError(ex, $"@MMF.SetViewVarMMF : cannot Serialize FS {ViewStateID}")
FS.Flush()
End Try
Try
FS.Flush()
Catch ex As Exception
End Try
End Sub
Public Function GetViewVarMMF(ViewStateID As Integer, key As String) As Object
Dim Bag = GetViewMMF(ViewStateID)
Dim Obj As Object = Nothing
If Bag.TryGetValue(key, Obj) Then
Return Obj
Else
Return Nothing
End If
Bag = Nothing
End Function
Public AllUserContainer As New Dictionary(Of Integer, UserContainer)(50)
Public Sub SetUserContainer(Usr As Integer, Con As UserContainer)
Con.UserID = Usr
If AllUserContainer.ContainsKey(Usr) Then
AllUserContainer(Usr) = Con
Con.Time = Now
Else
Log($"Added new user {Usr}")
AllUserContainer.Add(Usr, Con)
Con.Time = Now
End If
End Sub
Public Function GetUserContainer(Usr As Integer) As UserContainer
Dim Con As UserContainer = Nothing
If AllUserContainer.TryGetValue(Usr, Con) Then
Con.Time = Now
Return Con
Else
Log($"Added new user {Usr}")
Con = New UserContainer(Usr)
AllUserContainer.Add(Usr, Con)
Con.Time = Now
Return Con
End If
End Function
'___________________________________________________'
Public Sub SetViewVar(ViewStateID As Integer, key As String, Obj As Object)
If PreferMemoryMapFiles Then
SetViewVarMMF(ViewStateID, key, Obj)
Else
SetViewVarRAM(ViewStateID, key, Obj)
End If
End Sub
Public Function GetViewVar(ViewStateID As Integer, key As String) As Object
If PreferMemoryMapFiles Then
Return GetViewVarMMF(ViewStateID, key)
Else
Return GetViewVarRAM(ViewStateID, key)
End If
End Function
Public Sub RemoveMMF(ViewStateID As Integer)
Dim FS As FileStream = Nothing
If MMFStreams.TryGetValue(ViewStateID, FS) Then
Try
FS.Close()
Catch ex As Exception
End Try
End If
End Sub
Public Sub RemoveUserContainer(Usr As Integer)
If AllUserContainer.ContainsKey(Usr) Then
AllUserContainer(Usr).Dispose()
AllUserContainer.Remove(Usr)
Log($"Removed user {Usr}")
End If
End Sub
Public Sub DeleteUnusedMMFs()
Dim Files = Directory.GetFiles(FilePathMMFs)
Dim nowTime As Date = Now
Dim nOfFiles = 0I
For Each FilePath In Files
Dim FileID = Path.GetFileName(FilePath)
Dim Time As Date = Date.MinValue
If UserStates.MMFStreamsTimes.TryGetValue(FileID, Time) Then
If Time.AddMinutes(5) < nowTime Then
Try
UserStates.MMFStreams(FileID).Close()
Catch ex As Exception
End Try
Try
File.Delete(FilePath)
nOfFiles += 1
Catch ex As Exception
End Try
End If
Else
Try
File.Delete(FilePath)
nOfFiles += 1
Catch ex As Exception
End Try
End If
Next
Log($"@ViewStates.DeleteUnusedMMFs : {nOfFiles} deleted")
End Sub
'___________________________________________________'
Public Sub ClearUnusedViewStates()
Dim BeforeRAM = (My.Application.Info.WorkingSet / 1024) / 1024
Dim CurrTime = Now
Dim ToRemove As New List(Of Integer)
Dim ViewEntries As Integer
Dim UsrEntries As Integer
If ViewStatusBags.Count = 0 Then
GoTo RemoveusrsLbl
End If
For i = ViewStatusBags.Count - 1 To 0 Step -1
Dim Time = ViewStatusTimes.ElementAt(i).Value
If Time.AddMinutes(5) < CurrTime Then
ToRemove.Add(ViewStatusBags.ElementAt(i).Key)
End If
Next
ViewEntries = ToRemove.Count
For Each i In ToRemove
ViewStatusBags.Remove(i)
Next
RemoveusrsLbl:
If AllUserContainer.Count = 0 Then
GoTo Final
End If
For i = AllUserContainer.Count - 1 To 0 Step -1
If AllUserContainer(i).Time.AddMinutes(15) < CurrTime Then
AllUserContainer.Remove(AllUserContainer(i).UserID)
UsrEntries += 1
End If
Next
Final:
GC.Collect()
Dim AfterRAM = (My.Application.Info.WorkingSet / 1024) / 1024
Log($"@ViewStates : {ViewEntries} Unused ViewStates Cleared. {UsrEntries} inactive users cleared. {AfterRAM - BeforeRAM} MB Cleared. ")
End Sub
End Module
(C# 代码)(已翻译)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualBasic;
using System.Runtime.Serialization.Formatters.Binary;
using System.Web.UI;
public static class UserStates
{
public static int CurrSessionVariableIndex
{
get
{
int I;
if (LDB.CustomData.TryGetValue("CurrSessionIndex", I))
return I;
else
{
LDB.CustomData("CurrSessionIndex") = 1;
return I;
}
}
set
{
LDB.CustomData("CurrSessionIndex") = value;
}
}
public static int NewSessionVariableIndex()
{
CurrSessionVariableIndex += 1;
return CurrSessionVariableIndex;
}
public static bool PreferMemoryMapFiles = true;
public static Dictionary<int, Dictionary<string, object>> ViewStatusBags = new Dictionary<int, Dictionary<string, object>>(300);
public static Dictionary<int, DateTime> ViewStatusTimes = new Dictionary<int, DateTime>(300);
public static void SetViewVarRAM(int ViewStateID, string key, object Obj)
{
Dictionary<string, object> Bag = null;
if (ViewStatusBags.TryGetValue(ViewStateID, out Bag))
{
try
{
Bag[key] = Obj;
}
catch (Exception ex)
{
Log($"Added new ViewBag.Var {ViewStateID}.{key}");
Bag.Add(key, Obj);
}
ViewStatusTimes[ViewStateID] = DateTime.Now;
}
else
{
Log($"Added new ViewBag {ViewStateID}");
Bag = new Dictionary<string, object>();
ViewStatusBags.Add(ViewStateID, Bag);
ViewStatusTimes.Add(ViewStateID, DateTime.Now);
Bag.Add(key, Obj);
}
}
public static object GetViewVarRAM(int ViewStateID, string key)
{
Dictionary<string, object> Bag = null;
if (ViewStatusBags.TryGetValue(ViewStateID, out Bag))
{
ViewStatusTimes[ViewStateID] = DateTime.Now;
try
{
return Bag[key];
}
catch (Exception ex)
{
Log($"Added new ViewBag.Var {ViewStateID}.{key}");
Bag.Add(key, null);
return Bag[key];
}
}
else
{
Log($"Added new ViewBag {ViewStateID}");
Bag = new Dictionary<string, object>();
ViewStatusBags.Add(ViewStateID, Bag);
ViewStatusTimes.Add(ViewStateID, DateTime.Now);
Bag.Add(key, null);
return Bag[key];
}
}
public static Dictionary<string, object> GetViewMMF(int ViewStateID)
{
FileStream FS = null;
BinaryFormatter BF = new BinaryFormatter();
GetFileStream(ref ViewStateID, ref FS);
Dictionary<string, object> Bag;
try
{
Bag = BF.Deserialize(FS);
}
catch (Exception ex)
{
if (!ex.Message.StartsWith("Attempting to deserialize an empty stream"))
LogError(ex, $"@MMF.Get : cannot Deserialize FS {ViewStateID}");
FS.Flush();
Bag = new Dictionary<string, object>();
SetViewMMF(ViewStateID, Bag);
}
try
{
FS.Flush();
}
catch (Exception ex)
{
}
return Bag;
}
public static void SetViewMMF(int ViewStateID, Dictionary<string, object> Bag)
{
FileStream FS = null;
BinaryFormatter BF = new BinaryFormatter();
GetFileStream(ref ViewStateID, ref FS);
try
{
BF.Serialize(FS, Bag);
}
catch (Exception ex)
{
LogError(ex, $"@MMF.Set : cannot Serialize FS {ViewStateID}");
FS.Flush();
}
try
{
FS.Flush();
}
catch (Exception ex)
{
}
}
public static Dictionary<int, FileStream> MMFStreams = new Dictionary<int, FileStream>(100);
public static Dictionary<int, DateTime> MMFStreamsTimes = new Dictionary<int, DateTime>(100);
public static string FilePathMMFs;
private static void GetFileStream(ref int ViewStateID, ref FileStream FS)
{
if (MMFStreams.TryGetValue(ViewStateID, out FS))
{
try
{
FS.Seek(0, SeekOrigin.Begin);
}
catch (Exception ex)
{
LogError(ex, $"@MMF.Set : cannot restart FS {ViewStateID}");
FS = new FileStream(FilePathMMFs + ViewStateID.ToString() + "-" + Rand.Next(100, 1000).ToString, FileMode.OpenOrCreate);
FS.Seek(0, SeekOrigin.Begin);
MMFStreams[ViewStateID] = FS;
}
MMFStreamsTimes[ViewStateID] = DateTime.Now;
}
else
{
try
{
FS = new FileStream(FilePathMMFs + ViewStateID.ToString(), FileMode.OpenOrCreate);
FS.Seek(0, SeekOrigin.Begin);
MMFStreams.Add(ViewStateID, FS);
}
catch (Exception ex)
{
LogError(ex, $"@MMF.Set : cannot OpenOrCreate new FS {ViewStateID}");
FS = new FileStream(FilePathMMFs + ViewStateID.ToString() + "-" + Rand.Next(100, 1000).ToString, FileMode.OpenOrCreate);
FS.Seek(0, SeekOrigin.Begin);
MMFStreams.Add(ViewStateID, FS);
}
MMFStreamsTimes[ViewStateID] = DateTime.Now;
}
}
public static void SetViewVarMMF(int ViewStateID, string key, object Obj)
{
FileStream FS = null;
BinaryFormatter BF = new BinaryFormatter();
GetFileStream(ref ViewStateID, ref FS);
Dictionary<string, object> Bag;
try
{
Bag = BF.Deserialize(FS);
}
catch (Exception ex)
{
// LogError(ex, $"@MMF.SetViewVarMMF : cannot Deserialize FS {ViewStateID}. saved new bag")
Bag = new Dictionary<string, object>();
}
FS.Seek(0, SeekOrigin.Begin);
if (Bag.ContainsKey(key))
Bag[key] = Obj;
else
Bag.Add(key, Obj);
try
{
BF.Serialize(FS, Bag);
}
catch (Exception ex)
{
LogError(ex, $"@MMF.SetViewVarMMF : cannot Serialize FS {ViewStateID}");
FS.Flush();
}
try
{
FS.Flush();
}
catch (Exception ex)
{
}
}
public static object GetViewVarMMF(int ViewStateID, string key)
{
var Bag = GetViewMMF(ViewStateID);
object Obj = null;
if (Bag.TryGetValue(key, out Obj))
return Obj;
else
return null;
Bag = null;
}
public static Dictionary<int, UserContainer> AllUserContainer = new Dictionary<int, UserContainer>(50);
public static void SetUserContainer(int Usr, UserContainer Con)
{
Con.UserID = Usr;
if (AllUserContainer.ContainsKey(Usr))
{
AllUserContainer[Usr] = Con;
Con.Time = DateTime.Now;
}
else
{
Log($"Added new user {Usr}");
AllUserContainer.Add(Usr, Con);
Con.Time = DateTime.Now;
}
}
public static UserContainer GetUserContainer(int Usr)
{
UserContainer Con = null/* TODO Change to default(_) if this is not a reference type */;
if (AllUserContainer.TryGetValue(Usr, out Con))
{
Con.Time = DateTime.Now;
return Con;
}
else
{
Log($"Added new user {Usr}");
Con = new UserContainer(Usr);
AllUserContainer.Add(Usr, Con);
Con.Time = DateTime.Now;
return Con;
}
}
// ___________________________________________________'
public static void SetViewVar(int ViewStateID, string key, object Obj)
{
if (PreferMemoryMapFiles)
SetViewVarMMF(ViewStateID, key, Obj);
else
SetViewVarRAM(ViewStateID, key, Obj);
}
public static object GetViewVar(int ViewStateID, string key)
{
if (PreferMemoryMapFiles)
return GetViewVarMMF(ViewStateID, key);
else
return GetViewVarRAM(ViewStateID, key);
}
public static void RemoveMMF(int ViewStateID)
{
FileStream FS = null;
if (MMFStreams.TryGetValue(ViewStateID, out FS))
{
try
{
FS.Close();
}
catch (Exception ex)
{
}
}
}
public static void RemoveUserContainer(int Usr)
{
if (AllUserContainer.ContainsKey(Usr))
{
AllUserContainer[Usr].Dispose();
AllUserContainer.Remove(Usr);
Log($"Removed user {Usr}");
}
}
public static void DeleteUnusedMMFs()
{
var Files = Directory.GetFiles(FilePathMMFs);
DateTime nowTime = DateTime.Now;
var nOfFiles = 0;
foreach (var FilePath in Files)
{
var FileID = Path.GetFileName(FilePath);
DateTime Time = DateTime.MinValue;
if (UserStates.MMFStreamsTimes.TryGetValue(FileID, out Time))
{
if (Time.AddMinutes(5) < nowTime)
{
try
{
UserStates.MMFStreams[FileID].Close();
}
catch (Exception ex)
{
}
try
{
File.Delete(FilePath);
nOfFiles += 1;
}
catch (Exception ex)
{
}
}
}
else
try
{
File.Delete(FilePath);
nOfFiles += 1;
}
catch (Exception ex)
{
}
}
Log($"@ViewStates.DeleteUnusedMMFs : {nOfFiles} deleted");
}
// ___________________________________________________'
public static void ClearUnusedViewStates()
{
var BeforeRAM = (My.Application.Info.WorkingSet / (double)1024) / (double)1024;
var CurrTime = DateTime.Now;
List<int> ToRemove = new List<int>();
int ViewEntries;
int UsrEntries;
if (ViewStatusBags.Count == 0)
goto RemoveusrsLbl;
for (var i = ViewStatusBags.Count - 1; i >= 0; i += -1)
{
var Time = ViewStatusTimes.ElementAt(i).Value;
if (Time.AddMinutes(5) < CurrTime)
ToRemove.Add(ViewStatusBags.ElementAt(i).Key);
}
ViewEntries = ToRemove.Count;
foreach (var i in ToRemove)
ViewStatusBags.Remove(i);
RemoveusrsLbl:
;
if (AllUserContainer.Count == 0)
goto Final;
for (var i = AllUserContainer.Count - 1; i >= 0; i += -1)
{
if (AllUserContainer[i].Time.AddMinutes(15) < CurrTime)
{
AllUserContainer.Remove(AllUserContainer[i].UserID);
UsrEntries += 1;
}
}
Final:
;
GC.Collect();
var AfterRAM = (My.Application.Info.WorkingSet / (double)1024) / (double)1024;
Log($"@ViewStates : {ViewEntries} Unused ViewStates Cleared. {UsrEntries} inactive users cleared. {AfterRAM - BeforeRAM} MB Cleared. ");
}
}