我正在尝试使应用程序重启/崩溃/结束持久队列(或List ..)。即:我需要在应用程序运行时添加内容并在以后删除内容。在这两个位置之间,应用程序可以重新启动多次(或者崩溃,或者已经为我所知道的任务结束了。)
我的第一个想法就是简单地创建一个mylist.txt
文件来逐行存储数据,并在我需要时添加行到最后一行,并在完成后删除第一行。
问题是一段时间后文本文件中可能有数千行,如果不读取并重写整个文件,就无法删除其中的第一行。
有没有什么好方法可以实现这一点,因为不断阅读和编写整个文件不是一种选择?
编辑1 :我正在研究SQLite,但我更愿意不再添加依赖项或.dll,如果可能的话,不能ILMerged。
编辑2:应用程序不能依赖任何外部服务器来跟踪它的内容。
编辑3:对ILMerge兼容的本地数据库的建议也是一种可接受的解决方案。
答案 0 :(得分:2)
软件中持久队列的正确解决方案是使用持久性队列包。
我们称之为Message Queue库。
Microsoft Windows内置了一个名为MSMQ的内容。但是我建议使用RabbitMQ,或者如果你想要一个进程内解决方案,你可以尝试使用Ayende的Rhino Queues。
答案 1 :(得分:0)
使用数据库,持久化数据并编辑/删除它正是它们的用途,并且有一些好的免费的,试试mysql
答案 2 :(得分:0)
我自己实现了这个,只使用文件夹中的文件。它不是有史以来最快的列表,但它完成了工作,没有外部依赖。在我的笔记本电脑上,它在4秒钟内插入4000件物品,然后在12点读回。
非常欢迎任何有关如何更快或更好的建议;)
以下是测试用法:
PersistantQueue list = new PersistantQueue("queuefolder");
foreach (var i in Enumerable.Range(1, 100000))
{
list.Add(i + "_" + Guid.NewGuid());
if(i % 1000 == 0)
Console.WriteLine("c: "+ DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss:fff ->") + i);
}
string msg = null;
int b = 0;
while ((msg = list.GetNext()) != null)
{
b++;
if (b % 1000 == 0)
Console.WriteLine("r: " + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss:fff ->") + b);
}
Console.WriteLine("done");
和班级
public class PersistantQueue
{
private string _FolderPath = "";
private long _FileIdCounter = 0;
private readonly object _LockObject = new object();
public PersistantQueue()
{
Init("PersistantList");
}
public PersistantQueue(string folderPath)
{
Init(folderPath);
}
private void Init(string folderPath)
{
_FolderPath = folderPath;
if (string.IsNullOrWhiteSpace(folderPath.Trim()) == true)
throw new Exception("Invalid folder name");
if (Directory.Exists(_FolderPath) == false)
Directory.CreateDirectory(_FolderPath);
}
public void Add(string Item)
{
lock (_LockObject)
{
_FileIdCounter++;
string file = DateTime.Now.ToString("yyyyMMddhhmmssfff") + "_" + _FileIdCounter;
string path = (_FolderPath + @"\" + file);
using (StreamWriter sw = File.CreateText(path))
{
sw.Write(Item);
}
}
}
public string GetNext()
{
string result = null;
lock (_LockObject)
{
DirectoryInfo di = new DirectoryInfo(_FolderPath);
var firstFileName = di.EnumerateFiles()
.Select(f => f.Name)
.FirstOrDefault();
string path = (_FolderPath + @"\" + firstFileName);
result = File.ReadAllText(path);
File.Delete(path);
}
return result;
}
}