并发地写入StorageFile
本文关键字:StorageFile 并发 | 更新日期: 2023-09-27 18:04:18
如何在Windows Phone 8.1中同时写入一些文本到StorageFile ?我试图在c#中实现lock
提供的互斥锁,但我无法打开我想在lock
块中写入的文件流。
这就是我正在做的:
StorageFile file = await folder.GetFileAsync(logFileName);
// Lock file access object and open filestream for writing.
lock (fileLockObject)
{
StreamWriter writer = new StreamWriter(await file.OpenStreamForWriteAsync());
writer.Write(sometext);
}
但lock
不允许async
在其体内进行任何形式的操作。如果不使用像AsyncLock
这样的第三方库,我怎么能仍然保持互斥锁和并发?
在async
操作中,您需要使用 AsyncLock
代替lock
private readonly AsyncLock asyncLocker = new AsyncLock();
.....
using(await asyncLocker.LockAsync())
{
enter code here
}
AsyncLock msdn, github
通常在这种情况下,您希望写操作尽可能有序,并希望将实际写操作卸载到另一个线程。下面是一个简化的示例,但是在大多数情况下,您将希望对其进行优化,以便在需要时结束并重新启动线程。
AutoResetEvent _waitHandle = new AutoResetEvent(false);
List<string> _writeCache = new List<string>();
bool _threadRunning = false;
void WriteToFile(string text)
{
lock (_writeCache)
{
_writeCache.Add(text);
_waitHandle.Set();
if(_threadRunning)
{
return;
}
_threadRunning = true;
}
Task.Run(async () =>
{
while (true)
{
_waitHandle.WaitOne();
StorageFile file = await folder.GetFileAsync(logFileName);
using (var f = await file.OpenStreamForWriteAsync())
{
using (StreamWriter writer = new StreamWriter(await file.OpenStreamForWriteAsync()))
{
lock (_writeCache)
{
while (_writeCache.Count > 0)
{
string s = _writeCache[0];
_writeCache.RemoveAt(0);
writer.Write(s);
}
}
}
}
}
});
}
我可以使用信号量来解决这个问题。在写入文件之前,我使用SlimSemaphore()
获取和释放单个资源的信号量。这允许使用await操作,并消除了lock
和mutex
的限制,因为您可以在块中运行await
操作(mutex
和lock
实际上不允许)。
// define semaphore with only one resource to allocate.
SemaphoreSlim semaphore = new SemaphoreSlim(1);
// acquire semaphore
await semaphore.WaitAsync();
try { // write to file }
catch { // catch any exception }
finally
{
semaphore.Release();
}
由于您确实需要使用lock
语句,您可以尝试:
using System.Threading.Tasks;
public async Task WriteToFile(string text)
{
StorageFile file = await folder.GetFileAsync(logFileName);
lock (fileLockObject)
{
Task<Stream> streamTask = file.OpenStreamForWriteAsync();
try
{
streamTask.Wait();
}
catch (AggregateException ex)
{
// You may want to handle errors here
}
if (!streamTask.IsFaulted)
{
using (StreamWriter writer = new StreamWriter(streamTask.Result))
{
writer.Write(text);
}
}
}
}
用法(假设这是一个事件处理程序,否则使用public async Task YourMethod(...)
):
public async void YourMethod()
{
// 1. Blocks UI thread
Task t = WriteToFile("text");
t.Wait();
// or
// 2. Does not block UI thread
await WriteToFile("text");
}
试试这个代码
public static void WriteLog(string Error)
{
using (StreamWriter logfile = new StreamWriter(filePath + "Log.txt", true))
{
logfile.WriteLine(DateTime.Now.ToString() + ":" + DateTime.Now.Millisecond.ToString() + " -@: " + Error);
logfile.Close();
}
}