I have a Xamarin Forms application running in Android 7.1, in which several objects have to concurrently write lines into a single shared file. So, I created the following class Log.cs, following the Microsoft documentation about the ReaderWriterLockSlim semaphore which is dedicated to conccurent access to shared file. Note that the project in which is included the Log class is a PCL project and the library used is PCLStorage, as I cannot use the System.IO namespace inside PCL project.
public sealed class Log
{
private static string MyFileName = "MyPathToTheSharedFilename";
private static ReaderWriterLockSlim _logFileLock = new ReaderWriterLockSlim();
// The public async function used by all objects to write concurrently into file.
public void WriteLog(
string format,
params object[] args)
{
Task.Run(() => WriteAsync(format, args));
}
// The private method which access the lock and actually write lines into the file
private async Task WriteAsync(
string format,
params object[] args)
{
_logFileLock.EnterWriteLock();
try
{
// Check whether the file exists.
var logFileExists = await logFolder.CheckExistsAsync(MyFileName);
IFile logFile = null;
if (logFileExists == ExistenceCheckResult.NotFound)
logFile = await logFolder.CreateFileAsync(MyFileName, CreationCollisionOption.OpenIfExists);
else
logFile = await logFolder.GetFileAsync(MyFileName);
if (logFile == null)
return;
using (StreamWriter streamWriter = new StreamWriter(logFile.OpenAsync(FileAccess.ReadAndWrite).Result))
{
// Always append the text to write to the end of the file.
streamWriter.BaseStream.Seek(0, SeekOrigin.End);
streamWriter.WriteLine(string.Format(format, args));
streamWriter.Flush();
}
}
catch (Exception)
{
// I do not know what to do in case there is an exception, maybe try to create a new file???
}
finally
{
_logFileLock.ExitWriteLock();
}
}
}
And below is an example of use from another class:
public class AnotherClassWithNeedsToWriteToSharedFile
{
private Log myLog = IoCService.Resolve<Log>(); // Resolve the singleton type Log.
public WriteToTheSharedFile(string textToWrite)
{
myLog.WriteLog("{0:yyyy-MM-dd HH:mm:ss:fff}|{1}", DateTime.Now, "|Information|File");
}
}
Everything works fine, I tested my code using Parallel.Foreach loops thoroughly, but in production, sometimes, I get a very long of several thousands of NULL character as depicted in the following screenshot I got, as if the log file could not actually write the text to the file, but after every such NULL line, my application crashes. No class that use the Log class writes NULL characters on purpose.
I would like to understand why and what makes the Log class write NULL characters like that, or at least how can I managed to find out?
Any suggestion or help will be highly appreciated. Thanks in advance.