如何在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
这样的第三方库,我怎样才能保持互斥和并发?
答案 0 :(得分:2)
在async
操作中,您需要使用 AsyncLock
而不是lock
private readonly AsyncLock asyncLocker = new AsyncLock();
.....
using(await asyncLocker.LockAsync())
{
enter code here
}
答案 1 :(得分:2)
通常在这种情况下,您希望写入尽可能顺序,并且您希望将实际写入卸载到另一个单个线程。下面是一个简化的示例,但在大多数情况下,您需要优化它以在需要时结束并重新启动线程。
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);
}
}
}
}
}
});
}
答案 2 :(得分:1)
我能够使用信号量来解决这个问题。我使用SlimSemaphore()
来获取和释放具有单个资源的信号量,然后写入文件。这样就可以使用等待操作并删除与lock
和mutex
相关的限制,因为您可以在块中运行await
个操作(mutex
和lock
并且#39; t真的允许)。
// 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();
}
答案 3 :(得分:0)
由于您确实需要使用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");
}
答案 4 :(得分:-1)
试试此代码
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();
}
}