C# 并发文件访问
我正在运行一个应用程序的多个实例,该应用程序从文件中读取第一行,然后删除第一行并以相同的名称保存文件。我发现在某些情况下,应用程序会崩溃。我创建了一个示例程序,只是为了更好地理解我遇到的问题。 如果我运行这个程序的四个实例,有时多个实例会试图删除同一行。最后操作成功了,但效率不高。如何改进代码以避免这种情况?也许每个实例在使用文件时都需要锁定该文件C# 并发文件访问,c#,winforms,C#,Winforms,我正在运行一个应用程序的多个实例,该应用程序从文件中读取第一行,然后删除第一行并以相同的名称保存文件。我发现在某些情况下,应用程序会崩溃。我创建了一个示例程序,只是为了更好地理解我遇到的问题。 如果我运行这个程序的四个实例,有时多个实例会试图删除同一行。最后操作成功了,但效率不高。如何改进代码以避免这种情况?也许每个实例在使用文件时都需要锁定该文件 using System; using System.Collections.Generic; using System.Drawing; usin
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Diagnostics;
namespace ConcurrentFileAccess
{
public partial class MainForm : Form
{
bool gbAbort = false;
public MainForm()
{
InitializeComponent();
}
void BtnCreateFileClick(object sender, EventArgs e)
{
string sFile = @"S:\Temp\concurrentFileAccess.txt";
Stopwatch stopwatch = Stopwatch.StartNew();
if (File.Exists(sFile)) {
File.Delete(sFile);
}
if (!File.Exists(sFile)) {
List<string> list = new List<string>();
var fc = File.Create(sFile);
fc.Close();
for (int i = 1; i <= 200; i++) {
list.Add(i.ToString());
}
File.WriteAllLines(sFile, list);
listBox1.Items.Add("File " + sFile + " was created and it contains 200 lines");
} else {
string[] lines = File.ReadAllLines(sFile);
int nlines = lines.Length;
listBox1.Items.Add("File " + sFile + " already exists and it contains " + nlines + " lines");
}
stopwatch.Stop();
listBox1.Items.Add("File created in " + stopwatch.Elapsed.ToString("hh\\:mm\\:ss\\.fff"));
}
void BtnDeleteFromFileClick(object sender, EventArgs e)
{
gbAbort = false;
int nlines = 9999;
while (nlines > 0) {
nlines = DeleteOneLine();
Application.DoEvents();
if (gbAbort) {
return;
}
}
}
int DeleteOneLine()
{
string sFile = @"S:\Temp\concurrentFileAccess.txt";
listBox1.Items.Add("We are in DeleteLines()...");
listBox1.SelectedIndex = listBox1.Items.Count - 1;
Application.DoEvents();
int nLinesLeft = 9999;
string line0 = string.Empty;
Stopwatch stopwatch = Stopwatch.StartNew();
int ntry = 0;
while (ntry < 100) {
try {
string[] lines = File.ReadAllLines(sFile);
List<string> list = new List<string>(lines);
nLinesLeft = list.Count;
if (nLinesLeft > 0) {
line0 = list[0];
list.RemoveAt(0);
listBox1.Items.Add("Deleted line " + line0);
listBox1.SelectedIndex = listBox1.Items.Count - 1;
Application.DoEvents();
listBox1.Items.Add("Writing to file after line " + line0 + " was deleted");
File.WriteAllLines(sFile, list);
nLinesLeft = list.Count;
Application.DoEvents();
} else {
nLinesLeft = 0;
break;
}
} catch (Exception) {
ntry++;
listBox1.Items.Add("ntry = " + ntry + ", could not delete line " + line0 + " from file. Attempting again...");
listBox1.SelectedIndex = listBox1.Items.Count - 1;
Application.DoEvents();
Application.DoEvents();
Thread.Sleep(50);
}
}
if(ntry >= 100) {
nLinesLeft = -1; // should never get here
}
stopwatch.Stop();
listBox1.Items.Add("ntry: " + ntry + ", lines Left: " + nLinesLeft + ", elapsed = " + stopwatch.Elapsed.ToString("hh\\:mm\\:ss\\.fff"));
listBox1.SelectedIndex = listBox1.Items.Count - 1;
Application.DoEvents();
return nLinesLeft;
}
void BtnAbortClick(object sender, EventArgs e)
{
gbAbort = true;
}
void BtnOpenAppFolderClick(object sender, EventArgs e)
{
string sFile = Application.ExecutablePath;
string sPath = Path.GetDirectoryName(sFile);
Process.Start(sPath);
}
void BtnOpenFileClick(object sender, EventArgs e)
{
string sFile = @"S:\Temp\concurrentFileAccess.txt";
if(File.Exists(sFile)) {
Process.Start(sFile);
}
else {
MessageBox.Show("File " + sFile + " not found");
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用系统图;
使用System.Windows.Forms;
使用System.IO;
使用系统线程;
使用系统诊断;
命名空间ConcurrentFileAccess
{
公共部分类主窗体:窗体
{
bool-gbAbort=false;
公共表格(
{
初始化组件();
}
void BtnCreateFileClick(对象发送者,事件参数e)
{
字符串sFile=@“S:\Temp\concurrentFileAccess.txt”;
秒表秒表=Stopwatch.StartNew();
if(File.Exists(sFile)){
文件删除(sFile);
}
如果(!File.Exists(sFile)){
列表=新列表();
var fc=File.Create(sFile);
fc.Close();
对于(int i=1;i 0){
nlines=DeleteOneLine();
Application.DoEvents();
伊夫(巴博尔特){
返回;
}
}
}
int DeleteOneLine()
{
字符串sFile=@“S:\Temp\concurrentFileAccess.txt”;
listBox1.Items.Add(“我们在DeleteLines()…”;
listBox1.SelectedIndex=listBox1.Items.Count-1;
Application.DoEvents();
int nLinesLeft=9999;
string line0=string.Empty;
秒表秒表=Stopwatch.StartNew();
intntry=0;
而(ntry<100){
试一试{
string[]lines=File.ReadAllLines(sFile);
列表=新列表(行);
nLinesLeft=list.Count;
如果(nLinesLeft>0){
line0=列表[0];
移除列表(0);
listBox1.Items.Add(“删除行”+line0);
listBox1.SelectedIndex=listBox1.Items.Count-1;
Application.DoEvents();
listBox1.Items.Add(“删除第“+line0+”行后写入文件”);
File.writeAllines(sFile,list);
nLinesLeft=list.Count;
Application.DoEvents();
}否则{
nLinesLeft=0;
打破
}
}捕获(例外){
ntry++;
listBox1.Items.Add(“ntry=“+ntry+”,无法从文件中删除行“+line0+”。再次尝试…”);
listBox1.SelectedIndex=listBox1.Items.Count-1;
Application.DoEvents();
Application.DoEvents();
睡眠(50);
}
}
如果(ntry>=100){
nLinesLeft=-1;//不应该到这里
}
秒表;
列表框1.Items.Add(“ntry:+ntry+”,左行:“+nLinesLeft+”,已用=“+stopwatch.appeased.ToString”(“hh\\\:mm\\:ss\\\.fff”);
listBox1.SelectedIndex=listBox1.Items.Count-1;
Application.DoEvents();
返回nLinesLeft;
}
void BtnAbortClick(对象发送方,事件参数e)
{
gbAbort=true;
}
void BtnOpenAppFolderClick(对象发送方,事件参数e)
{
字符串sFile=Application.ExecutablePath;
string sPath=Path.GetDirectoryName(sFile);
过程启动(sPath);
}
void BtnOpenFileClick(对象发送方,事件参数e)
{
字符串sFile=@“S:\Temp\concurrentFileAccess.txt”;
if(File.Exists(sFile)){
进程启动(sFile);
}
否则{
Show(“文件”+sFile+“未找到”);
}
}
}
}
您可以使用a来实现。谢谢,这似乎是个好主意。我将尝试实现它。