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(); }
}
});
}
}
}