同时写入StorageFile

时间:2015-07-23 11:15:46

标签: c# concurrency windows-phone-8.1

如何在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这样的第三方库,我怎样才能保持互斥和并发?

5 个答案:

答案 0 :(得分:2)

async操作中,您需要使用 AsyncLock 而不是lock

    private readonly AsyncLock asyncLocker = new AsyncLock();
    .....
    using(await asyncLocker.LockAsync())
    {
       enter code here
    }

AsyncLock msdngithub

答案 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()来获取和释放具有单个资源的信号量,然后写入文件。这样就可以使用等待操作并删除与lockmutex相关的限制,因为您可以在块中运行await个操作(mutexlock并且#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();
    }
}