C# 这是否正确使用互斥来避免对文件的并发修改?

C# 这是否正确使用互斥来避免对文件的并发修改?,c#,silverlight,windows-phone-7,windows-phone-8,mutex,C#,Silverlight,Windows Phone 7,Windows Phone 8,Mutex,我希望能够将写入文件的代码放入互斥体,以避免对文件进行任何并发修改。但是,我只希望具有特定名称的文件被阻止为关键部分,而不是另一个文件。这段代码会像预期的那样工作吗?还是我遗漏了什么 private async static void StoreToFileAsync(string filename, object data) { IsolatedStorageFile AppIsolatedStorage = IsolatedStorageFile.GetUserSto

我希望能够将写入文件的代码放入互斥体,以避免对文件进行任何并发修改。但是,我只希望具有特定名称的文件被阻止为关键部分,而不是另一个文件。这段代码会像预期的那样工作吗?还是我遗漏了什么

private async static void StoreToFileAsync(string filename, object data)
    {
        IsolatedStorageFile AppIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication();
        if (IsolatedStorageFileExist(filename))
        {
            AppIsolatedStorage.DeleteFile(filename);
        }
        if (data != null)
        {
            string json = await Task.Factory.StartNew<string>(() => JsonConvert.SerializeObject(data));
            if (!string.IsNullOrWhiteSpace(json))
            {
                byte[] buffer = Encoding.UTF8.GetBytes(json);
                Mutex mutex = new Mutex(false, filename);
                mutex.WaitOne();
                IsolatedStorageFileStream ISFileStream = AppIsolatedStorage.CreateFile(filename);
                await ISFileStream.WriteAsync(buffer, 0, buffer.Length);
                ISFileStream.Close();
                mutex.ReleaseMutex();
            }
        }
    }

在一般情况下,将
互斥体
与异步代码一起使用是错误的。通常,我会说你应该使用类似的东西,如果你想要每个文件都有一个单独的锁,那么你需要一个字典或者类似的东西


但是,如果您的方法总是从UI线程调用,那么它就会工作。它不是很有效,但会起作用。

在一般情况下,将
互斥体
与异步代码一起使用是错误的。通常,我会说你应该使用类似的东西,如果你想要每个文件都有一个单独的锁,那么你需要一个字典或者类似的东西


但是,如果您的方法总是从UI线程调用,那么它就会工作。这不是很有效,但它会起作用。

您需要改进的地方很少:

  • 在互斥体内部运行异步代码是不好的,因为同一个线程应该创建和释放互斥体。当不是从UI线程调用时,可能会出现异常
  • filename
    对于互斥对象来说不是一个好名字-它是全局对象(在所有进程中),所以它应该是唯一的
  • 您应该处理互斥锁,并在finally子句中释放它(如果出现异常会发生什么情况?)-
  • 您应该/必须处理隔离流
  • 你还应该考虑无限等待是否是一个好的选择
  • 如果您没有访问文件amopng进程(Bacground代理、其他应用程序),则可以使用或

private async static void StoreToFileAsync(字符串文件名,对象数据)
{
使用(IsolatedStorageFile AppIsolatedStorage=IsolatedStorageFile.GetUserStoreForApplication())
{
if(IsolatedStorageFileExist(文件名))
AppIsolatedStorage.DeleteFile(文件名);
如果(数据!=null)
{
字符串json=await Task.Factory.StartNew(()=>JsonConvert.SerializeObject(data));
如果(!string.IsNullOrWhiteSpace(json))等待Task.Run(()=>
{
byte[]buffer=Encoding.UTF8.GetBytes(json);
使用(互斥互斥=新互斥(假,文件名))
{
尝试
{
mutex.WaitOne();
使用(IsolatedStorageFileStream ISFileStream=AppIsolatedStorage.CreateFile(文件名))
写入(buffer,0,buffer.Length);
}
捕获{}
最后{mutex.ReleaseMutex();}
}
});
}
}
}

编辑:从互斥体中删除了一个非连续调用-因为它在非从UI线程调用时会导致问题。

您应该改进以下几点:

  • 在互斥体内部运行异步代码是不好的,因为同一个线程应该创建和释放互斥体。当不是从UI线程调用时,可能会出现异常
  • filename
    对于互斥对象来说不是一个好名字-它是全局对象(在所有进程中),所以它应该是唯一的
  • 您应该处理互斥锁,并在finally子句中释放它(如果出现异常会发生什么情况?)-
  • 您应该/必须处理隔离流
  • 你还应该考虑无限等待是否是一个好的选择
  • 如果您没有访问文件amopng进程(Bacground代理、其他应用程序),则可以使用或

private async static void StoreToFileAsync(字符串文件名,对象数据)
{
使用(IsolatedStorageFile AppIsolatedStorage=IsolatedStorageFile.GetUserStoreForApplication())
{
if(IsolatedStorageFileExist(文件名))
AppIsolatedStorage.DeleteFile(文件名);
如果(数据!=null)
{
字符串json=await Task.Factory.StartNew(()=>JsonConvert.SerializeObject(data));
如果(!string.IsNullOrWhiteSpace(json))等待Task.Run(()=>
{
byte[]buffer=Encoding.UTF8.GetBytes(json);
使用(互斥互斥=新互斥(假,文件名))
{
尝试
{
mutex.WaitOne();
使用(IsolatedStorageFileStream ISFileStream=AppIsolatedStorage.CreateFile(文件名))
写入(buffer,0,buffer.Length);
}
捕获{}
最后{mutex.ReleaseMutex();}
}
});
}
}
}

编辑:从互斥体中删除了一个不连续的调用-因为当不是从UI线程调用时,它会导致问题。

我希望这能起作用。互斥是一种昂贵的内核对象。当只有一个进程(具有不同线程)访问文件时,您可以使用criticalsection。@Sivaraman您可以检查(edit1)criticalsection实现是否正确吗?可能更适合于此,我希望这能起作用。互斥是一种昂贵的内核对象。当只有一个进程(具有不同线程)访问文件时,您可以使用criticalsection。@Sivaraman您可以检查(edit1)criticalsection实现是否正确吗?可能更适合我不能使用锁定等待操作,那么,如果将WriteAsync替换为同步写入并作为单独的任务运行,可以吗?请看一下问题中的编辑1。顺便说一句,为什么我不应该在文件名上使用锁?我想应该可以。您只是在等待写入,所以在异步线程上运行Write时应该是相同的。至于命名锁-。我写道,命名互斥不是一个好的选择,例如,我认为您有
await Task.Factory.StartNew(() =>
                    {
                        if (!string.IsNullOrWhiteSpace(json))
                        {
                            byte[] buffer = Encoding.UTF8.GetBytes(json);
                            lock (filename)
                            {
                                IsolatedStorageFileStream ISFileStream = AppIsolatedStorage.CreateFile(filename);
                                ISFileStream.Write(buffer, 0, buffer.Length);
                                ISFileStream.Close();
                            }
                        }
                    });  
private async static void StoreToFileAsync(string filename, object data)
{
    using (IsolatedStorageFile AppIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
    {
        if (IsolatedStorageFileExist(filename))
            AppIsolatedStorage.DeleteFile(filename);
        if (data != null)
        {
            string json = await Task.Factory.StartNew<string>(() => JsonConvert.SerializeObject(data));
            if (!string.IsNullOrWhiteSpace(json)) await Task.Run(() =>
                {
                    byte[] buffer = Encoding.UTF8.GetBytes(json);
                    using (Mutex mutex = new Mutex(false, filename))
                    {
                        try
                        {
                            mutex.WaitOne();
                            using (IsolatedStorageFileStream ISFileStream = AppIsolatedStorage.CreateFile(filename))
                                ISFileStream.Write(buffer, 0, buffer.Length);
                        }
                        catch { }
                        finally { mutex.ReleaseMutex(); }
                    }
                });
        }
    }
}