我有一个应用程序,我打开一个日志文件进行写入。在某个时间点(当应用程序运行时),我用Excel 2003打开文件,表示文件应该以只读方式打开。那对我没关系。
但是我的申请引发了这个例外:
System.IO.IOException:进程无法访问该文件,因为另一个进程已锁定该文件的一部分。
我不明白Excel如何锁定文件(我的应用程序具有写访问权限),并导致我的应用程序无法写入文件!
为什么会这样?
(注意:我没有在Excel 2007中观察到这种行为。)
答案 0 :(得分:1)
这是一个记录同步锁的记录器。 (您可以根据自己的要求进行修改)
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Owf.Logger
{
public class Logger
{
private static object syncContoller = string.Empty;
private static Logger _logger;
public static Logger Default
{
get
{
if (_logger == null)
_logger = new Logger();
return _logger;
}
}
private Dictionary<Guid, DateTime> _starts = new Dictionary<Guid, DateTime>();
private string _fileName = "Log.txt";
public string FileName
{
get { return _fileName; }
set { _fileName = value; }
}
public Guid LogStart(string mesaage)
{
lock (syncContoller)
{
Guid id = Guid.NewGuid();
_starts.Add(id, DateTime.Now);
LogMessage(string.Format("0.00\tStart: {0}", mesaage));
return id;
}
}
public void LogEnd(Guid id, string mesaage)
{
lock (syncContoller)
{
if (_starts.ContainsKey(id))
{
TimeSpan time = (TimeSpan)(DateTime.Now - _starts[id]);
LogMessage(string.Format("{1}\tEnd: {0}", mesaage, time.TotalMilliseconds.ToString()));
}
else
throw new ApplicationException("Logger.LogEnd: Key doesn't exisits.");
}
}
public void LogMessage(string message)
{
lock (syncContoller)
{
string filePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
if (!filePath.EndsWith("\\"))
filePath += "\\owf";
else
filePath += "owf";
if (!Directory.Exists(filePath))
Directory.CreateDirectory(filePath);
filePath += "\\Log.txt";
lock (syncContoller)
{
using (StreamWriter sw = new StreamWriter(filePath, true))
{
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.sss") + "\t" + message);
}
}
}
}
}
}
答案 1 :(得分:0)
你怎么写日志?有你自己的开/关或使用一些三十方产品吗?
我认为只有在写入内容时才会打开和锁定日志。数据写入完成后,代码将关闭文件,当然还会释放锁
答案 2 :(得分:0)
我相信我遇到了同样类型的锁定问题,转载如下:
在某些时候,由于“文件被锁定”的消息,用户1无法保存文件。 关闭用户2的ReadOnly版本...锁定已释放,用户1现在可以再次保存。
如何在ReadOnly模式下打开文件会锁定该文件?
因此,它似乎是Excel2007问题或服务器问题。
答案 3 :(得分:0)
这似乎是一个.NET问题。 (好吧;如果你问我,就是一个Bug)。
基本上我通过使用以下多线程代码来复制问题:
Dim FS As System.IO.FileStream
Dim BR As System.IO.BinaryReader
Dim FileBuffer(-1) As Byte
If System.IO.File.Exists(FileName) Then
Try
FS = New System.IO.FileStream(FileName, System.IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
BR = New System.IO.BinaryReader(FS)
Do While FS.Position < FS.Length
FileBuffer = BR.ReadBytes(&H10000)
If FileBuffer.Length > 0 Then
... do something with the file here...
End If
Loop
BR.Close()
FS.Close()
Catch
ErrorMessage = "Error(" & Err.Number & ") while reading file:" & Err.Description
End Try
基本上,错误是尝试使用所有不同的共享模式(READ,WRITE,READ_WRITE)读取文件对文件锁定完全没有影响,无论你尝试什么;你总是会得到相同的结果:被锁定,不适用于任何其他用户。
微软甚至不会承认这个问题。
解决方案是使用内部Kernel32 CreateFile API来完成正确的访问,因为这可以确保操作系统在请求读取具有共享锁定或锁定访问权限的文件时听到您的请求。