线程的 C# 锁定文件 XML

C# lock file XML for threads

我对锁定声明有疑问

我看到的所有例子,锁定语句以相同的形式用于全局变量,但在我的情况下没有发生,那么我不知道如何避免错误"file is used for another..."

我的情况。 用户转到 form1,并在 form1 中向 XML 添加行。而在第二个平面中,线程获取 XML 并将信息发送到服务器并更新此 XML 中的状态对象。 然后当用户和线程同时写入时(一个由用户写入,另一个由第二个平面写入,xml 保存抛出错误) 我正在这样做

form1
{
  var A = takeAllABCObjects();
  var A = A + new objects();
  saveABCObjects(A);
}

Thread in second plane in all time life of app
{
  var B = takeAllABCObjects();
  B = UpdateObjectsB();
  saveABCObjects(B);
}


Class saveABCObjects(list<objects> ABCObjects)
{
 lock (ABCObjects)
 {
     XmlSerializer serializer = new XmlSerializer(typeof(List<objects>));
     TextWriter textWriter = new StreamWriter("ABC.xml");
     serializer.Serialize(textWriter, ABCObjects);
     textWriter.Close();
 }
}

那么我的问题是... lock语句使用错误? 我应该如何使用它?

Tnx,对不起我的工程师

如果您使用写权限和 "read" 共享权限打开文件,您应该没问题

所以 processA 打开写入

using(FileStream fs = File.Open("file.ext",FileMode.Open,FileAccess.Write,FileShare.Read))

进程 B 打开以供读取

using(FileStream fs = File.Open("file.ext",FileMode.Open,FileAccess.Read,FileShare.ReadWrite))

添加了一些代码,但它应该允许一个进程在另一个进程读取的同时写入

至于reader没过完就是另外一回事了

我会使用 wrapper class 访问您的 XML

因为你的两个线程不知道彼此何时访问文件,让 class 自己做。

我在想这样的事情:

public class SynchronizedXMLAccess : IDisposable
{
    private static readonly Mutex _access = new Mutex();
    public FileStream Fs { get; private set; }

    public SynchronizedXMLAccess(String path, FileMode mode = FileMode.Open, FileAccess access = FileAccess.ReadWrite, FileShare sharing = FileShare.None)
    {
        _access.WaitOne();
        Fs = File.Open(path, mode, access, sharing);
    }


    #region Implementation of IDisposable
    public void Dispose()
    {
        Fs.Close();
        _access.ReleaseMutex();
    }

    #endregion
}

}

您需要实例化 class 才能访问文件,但这将确保它只在线程之间打开一次。由于它实现了 IDisposable,您将能够使用 using 语句

实例化它

这是最基本的形式,所以如果你使用它,你将无法访问 2 个不同的文件,只能跨线程打开一个文件

编辑:

用法示例:

Class saveABCObjects(list<objects> ABCObjects)
{
  using(var sync = new SynchronizedXMLAccess(...)) 
  {
    XmlSerializer serializer = new XmlSerializer(typeof(List<objects>));
    TextWriter textWriter = new StreamWriter(sync.Fs);
    serializer.Serialize(textWriter, ABCObjects);
    textWriter.Close();
  }
}

基本问题是您的线程和窗体没有使用同一个锁对象。我不知道你是如何创建线程的,但我已经编写了一个带有 2 个任务的小控制台应用程序,这些任务将锁定并交替写入和读取文件。您必须将相同的锁定对象传递给每个任务才能使其工作。

static void Main(string[] args)
{
    var lockObject = new object();
    var fileName = @"C:\Users\kevin\Documents\test.txt";
    Action<object> action1 = (o) =>
    {
        var i = 0;
        while (i++ < 1000)
        {
            // do stuff that doesn't require the lock
            lock (o)
            {
                Console.WriteLine("In Thread1");
                // do stuff that does require the lock
                var text = File.ReadAllText(fileName);
                Console.WriteLine(text);
                File.WriteAllText(fileName, "\tThread1");
            }
        }
    };
    // Pass in our shared lock object
    Task task1 = new Task(action1, lockObject);
    task1.Start();
    Action<object> action2 = (o) =>
    {
        var i = 0;
        while (i++ < 1000)
        {
            // do stuff that doesn't require the lock
            lock (o)
            {
                // do stuff that does require the lock
                Console.WriteLine("In Thread2");
                var text = File.ReadAllText(fileName);
                Console.WriteLine(text);
                File.WriteAllText(fileName, "\tThread2");
            }
        }
    };
    // Pass in our shared lock object
    Task task2 = new Task(action2, lockObject);
    task2.Start();

    // sleep main thread and let the 2 threads do their stuff
    Thread.Sleep(5000);

    Console.ReadLine();
}