用于在页面之间写入的锁定(文件)?

时间:2012-11-16 19:00:40

标签: c# asp.net

我有一个应用程序,它使用XML文件来存储不需要在数据库中的某些数据。这个文件虽然很少,但可能会同时写入页面之间。这会产生一个问题,最有可能导致其中一个页面崩溃。我想知道是否有办法让页面渲染等待,直到另一个完成写入文件。

我不确定我是否可以假设每个页面渲染都在自己的线程中运行;如果是,那么我可以像lock()命令一样暂停该线程以等待资源可用。如果是这样,我如何在文件上实现lock()(因为它不是内存段)?

如果它没有线程或我不能使用lock(),还有哪些方法可以确保写入文件,但如果其他人正在使用该文件,它可以等待文件可用吗? / p>

管理订单和权利的方法很多,但为此很简单;如果你排在第二位,你会在另一个人完成后写下来。我此刻并不关心写冲突,但是并发写作是需要解决的问题。

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:2)

编辑:运行更多测试(单声道),我不太确定这是最好的方法。

我没有设法崩溃任何东西,但执行只是在Run()之后暂停几秒钟,然后回到呼叫者。所以我怀疑这不是支持这段代码的好兆头。

话虽如此,经过测试的情景远非现实。


另一种选择是以FileShare.ReadWrite模式打开文件,让操作系统关心锁定。

    public void Run()
    {
        var file = @"/home/me/test.txt";
        var threads = new Thread[3];

        for (int i = 0; i < threads.Length; i++) {
            int j = i;
            threads[j] = new Thread( s => { 
            Console.WriteLine("thread " + j + " is running...");
            using (var stream = File.Open(file, FileMode.OpenOrCreate, 
                   FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                Console.WriteLine("thread " + j + " is holding the file!");
                var data = ASCIIEncoding.ASCII.GetBytes("hello, I'm stream " + j);
                stream.Write(data, 0, data.Length);
                Thread.Sleep(1000);
            }});    
        }   

        foreach (var t in threads)
            t.Start();

        foreach (var t in threads)
            t.Join();

        Console.WriteLine(File.ReadAllText(file));
    }

输出:

thread 1 is running...
thread 0 is running...
thread 2 is running...
thread 2 is holding the file!
thread 1 is holding the file!
thread 0 is holding the file!
hello, I'm stream 0

答案 1 :(得分:1)

如果它来自一台机器,您可以使用Semaphore http://msdn.microsoft.com/en-us/library/system.threading.semaphore.aspx

private static Semaphore _fileSemaphore = new Semaphore(1, 1, "myFileGlobalSemaphore");

// later...

try
{
    _fileSemaphore.WaitOne();
    // do stuff..
}
finally
{
    _fileSemaphore.Release();
}

这有点像系统范围的锁定。但不是很好,会建议一个DB。另外,其他事情可能会导致文件访问失败。您可以使用适当的锁定模式实现创建FileStream的内容,如果您尝试打开以供两个来源写入,则会失败,但它不会执行类似lock的方案(使用内部Monitor

顺便说一句:“不需要存储在数据库中”。你问这个问题的事实表明它应该是。如果实施起来很麻烦,您可能需要重新考虑数据访问策略。像Code First的Entity Framework这样的东西可以很容易地“清除”数据库中的内容。

答案 2 :(得分:-2)

使用一些全局锁定对象。例如,添加到global.asax.cs:

public static readonly object FileLock = new Object();

然后在您的页面中使用:

lock(YourApplicationClass.FileLock)
{
    // do stuff
}