- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
现在,我正在尝试制作 a generic IsoStorageManager ,这将读/写和序列化/反序列化类异步,基于 this analytic .但是,我知道不同线程会请求相同文件进行读/写的情况。
我对这个领域的看法:
只需将所有 Reads()/Writes() 封装到一个锁中。 - 不太好,因为我不需要等待写入不同的文件。
为作者添加某种并发队列。如果同一个文件已经在处理中,writer 应该决定是要取消之前的任务(重写)还是从缓存中获取之前的任务并添加自己的更改(合并)。如果读者想要访问同一个文件,只需从队列中返回数据即可。 - 似乎过于复杂。
强制读者为所有作者使用一个线程。然后,我可以毫无问题地多次尝试访问同一文件。 - 作为临时解决方案似乎不错,这是这里的主要问题。其实和1一样。
EDIT1:也许我需要一个线程安全的字典?一旦要写入文件,我会将其名称和数据存储在字典中,这样读者就可以从编写者本身获取数据。
有什么建议吗?
编辑2:
我正在使用任务
public static async Task<T> ReadJsonAsyncTask<T>(this JsonTextReader reader)
{
return await TaskEx.Run(() => jsonSerializer.Deserialize<T>(reader));
}
像这样
public static async Task<T> ReadJsonEx<T>(String fileName)
{
if (String.IsNullOrEmpty(fileName))
return default(T);
return await await Task.Factory.StartNew(async () =>
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
using (var stream = new IsolatedStorageFileStream(fileName, FileMode.Open, store))
using (var sr = new StreamReader(stream))
using (var jr = new JsonTextReader(sr))
return await jr.ReadJsonAsyncTask<T>();
});
}
writer 也一样,我想确保在此过程中不会访问任何文件。
EDIT3:啊哈,看起来我在这里找到了答案:Easy way to save game in WP7 Silverlight?
EDIT4:这仅适用于同步调用。不是我的情况。 :(
EDIT5:经过一整天的搜索,我找到了 AsyncReaderWriterLock .用法很简单:
private static readonly AsyncReaderWriterLock readerLocker = new AsyncReaderWriterLock();
public static async Task<T> ReadJsonEx<T>(String fileName)
{
if (String.IsNullOrEmpty(fileName))
return default(T);
return await await Task.Factory.StartNew(async () =>
{
using (var locker = await readLocker.ReaderLockAsync())
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
using (var stream = new IsolatedStorageFileStream(fileName, FileMode.Open, store))
using (var sr = new StreamReader(stream))
using (var jr = new JsonTextReader(sr))
return await jr.ReadJsonAsyncTask<T>();
});
}
有时有效,有时无效。
EDIT6:好的,这里有一些关于我的 AsyncReaderWriterLock 测试用例的更多细节。我有前面提到的阅读器和使用自己的 AsyncReaderWriterLock 的编写器。我有一个带有进度条和按钮的页面。按钮命令是:
SimpleLogger.WriteLine("Starting generation...");
var list = new List<Order>();
//for (var i = 0; i < 10; i++)
list.Add(GenerateOrder());
SimpleLogger.WriteLine("Writing 5 times the same file...");
var res1 = await IsoStorageManager.WriteJsonEx(fileName1, list);
var res2 = await IsoStorageManager.WriteJsonEx(fileName1, list);
var res3 = await IsoStorageManager.WriteJsonEx(fileName1, list);
var res4 = await IsoStorageManager.WriteJsonEx(fileName1, list);
var res5 = await IsoStorageManager.WriteJsonEx(fileName1, list);
SimpleLogger.WriteLine("Writing 5 different files");
var res11 = await IsoStorageManager.WriteJsonEx(fileName1, list);
var res12 = await IsoStorageManager.WriteJsonEx(fileName2, list);
var res13 = await IsoStorageManager.WriteJsonEx(fileName3, list);
var res14 = await IsoStorageManager.WriteJsonEx(fileName4, list);
var res15 = await IsoStorageManager.WriteJsonEx(fileName5, list);
SimpleLogger.WriteLine("Reading 5 times the same");
var res21 = await IsoStorageManager.ReadJsonEx<List<Order>>(fileName1);
var res22 = await IsoStorageManager.ReadJsonEx<List<Order>>(fileName1);
var res23 = await IsoStorageManager.ReadJsonEx<List<Order>>(fileName1);
var res24 = await IsoStorageManager.ReadJsonEx<List<Order>>(fileName1);
var res25 = await IsoStorageManager.ReadJsonEx<List<Order>>(fileName1);
SimpleLogger.WriteLine("Reading 5 times different");
var res31 = await IsoStorageManager.ReadJsonEx<List<Order>>(fileName1);
var res32 = await IsoStorageManager.ReadJsonEx<List<Order>>(fileName2);
var res33 = await IsoStorageManager.ReadJsonEx<List<Order>>(fileName3);
var res34 = await IsoStorageManager.ReadJsonEx<List<Order>>(fileName4);
var res35 = await IsoStorageManager.ReadJsonEx<List<Order>>(fileName5);
SimpleLogger.WriteLine("Done");
如果按下按钮一次,或多或少可以(不同的文件不会同时写入,因为它应该在完美的世界中,但现在就这样吧):
09:03:38.262 [00:00:00.000] Starting generation...
09:03:38.300 [00:00:00.025] Writing 5 times the same file...
09:03:43.126 [00:00:04.811] Writing 5 different files
09:03:47.303 [00:00:04.163] Reading 5 times the same
09:03:50.194 [00:00:02.871] Reading 5 times different
09:03:53.341 [00:00:03.130] Done
如果多次按下按钮来模拟高负载和混合写入/读取内容,我得到以下输出:
08:51:52.680 [00:00:00.000] Starting generation...
08:51:52.722 [00:00:00.028] Writing 5 times the same file...
08:51:52.795 [00:00:00.057] Starting generation...
08:51:52.854 [00:00:00.043] Writing 5 times the same file...
08:51:52.892 [00:00:00.023] Starting generation...
08:51:52.922 [00:00:00.016] Writing 5 times the same file...
08:51:52.943 [00:00:00.006] Starting generation...
08:51:52.973 [00:00:00.016] Writing 5 times the same file...
08:52:06.009 [00:00:13.022] Writing 5 different files
08:52:06.966 [00:00:00.942] Writing 5 different files
08:52:07.811 [00:00:00.778] Writing 5 different files
08:52:08.513 [00:00:00.689] Writing 5 different files
08:52:22.115 [00:00:13.567] Reading 5 times the same
08:52:22.887 [00:00:00.755] Reading 5 times the same
08:52:23.773 [00:00:00.754] Reading 5 times the same
using (var stream = new IsolatedStorageFileStream(fileName, FileMode.Open, store))
System.IO.IOException occurred
_HResult=-2147024864
_message=[IO.IO_SharingViolation_File]
Arguments: Folder//TestFile1.txt
Debugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version=4.0.50829.0&File=mscorlib.dll&Key=IO.IO_SharingViolation_File
HResult=-2147024864
Message=[IO.IO_SharingViolation_File]
Arguments: Folder//TestFile1.txt
Debugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version=4.0.50829.0&File=mscorlib.dll&Key=IO.IO_SharingViolation_File
Source=mscorlib
StackTrace:
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
InnerException:
EDIT7:试过awaitable critical section .为单个命令(点击按钮)提供类似于 AsyncReaderWriterLock 结果:
03:12:05.213 [00:00:00.000] Starting generation...
03:12:05.252 [00:00:00.023] Writing 5 times the same file...
03:12:09.894 [00:00:04.626] Writing 5 different files
03:12:13.700 [00:00:03.792] Reading 5 times the same
03:12:16.831 [00:00:03.115] Reading 5 times different
03:12:20.032 [00:00:03.171] Done
而且这似乎通过碰撞测试(4 次快速按钮点击)更稳定:它设法在没有崩溃的情况下完成任务。
EDIT8:把所有的东西都移到了 Google Spreadshit .应该有一个很好的公共(public)访问(不需要登录)。稍后会将所有统计信息移到那里。
最佳答案
据我了解,您正计划创建一个可以异步运行的任务
。 IMO 最好的会在这里 Mutex - 它旨在保护共享资源免受多重访问:
When two or more threads need to access a shared resource at the same time, the system needs a synchronization mechanism to ensure that only one thread at a time uses the resource. Mutex is a synchronization primitive that grants exclusive access to the shared resource to only one thread. If a thread acquires a mutex, the second thread that wants to acquire that mutex is suspended until the first thread releases the mutex.
Mutex 的另一个优点是 in 可以是全局的 - 您可以使用它来保护进程之间对文件的访问。
据我内存WP8.0写文件,序列化是同步完成的,然后因为是单线程运行,Mutex的获取和释放不会有问题。
Here you can find a good pattern.
编辑
我仍然不明白您要实现的目标以及问题所在。 IMO 你正在将你的反序列化重定向到 ThreadPool 线程,然后你可以使那里的代码同步(它不在 UI 线程上运行)并使用 Mutex。可能还有许多其他解决方案,但也许这会有所帮助:
public static async Task<T> ReadJsonEx<T>(String fileName)
{
if (String.IsNullOrEmpty(fileName)) return default(T);
string mutexName = "dependantOnApp" + fileName;
return await Task.Run<T>(() =>
{
using (Mutex myMutex = new Mutex(false, mutexName))
{
try
{
myMutex.WaitOne();
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
using (var stream = new IsolatedStorageFileStream(fileName, FileMode.Open, store))
using (var sr = new StreamReader(stream))
using (var jr = new JsonTextReader(sr))
return jsonSerializer.Deserialize<T>(jr);
}
catch { throw new Exception("Exception"); }
finally { myMutex.ReleaseMutex(); }
}
});
}
关于c# - 异步读写器储物柜,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23582262/
我们希望能够为我们正在构建的 iOS 应用程序创建一个 IFC 阅读器,使我们能够渲染底层 BIM 生成的设计。我们发现了一个相当旧且不受支持的 C++ sdk here但这不是我们正在寻找的。 任何
void X() { lock(&m); while(x || y) wait( &farpar, &m); x ++; unlock(&m); // Do X stuff loc
如何实现 Reader Writer 问题,一次只允许一个 reader,并且只有在没有 writer 想要修改共享结构的情况下? Reader: wait(mutex)
我买了一个 USB RFID 读写器来开发考勤应用程序。除了设备,他们还提供了 VB 示例来读取/写入 RFID 标签。但我想用 Java 来做。有什么方法可以开始编程来读取/写入 RFID 标签。
我拿到了 RC-S380 NFC 读写器,但是在安装了 Sony 的驱动程序后,该设备在设备管理器中显示为“NFC 端口”而不是“感应设备”。 在我的应用程序中,ProximityDevice.Get
我是一名优秀的程序员,十分优秀!