我使用4个线程将数据写入文件。每个线程使用MMF来写入文件的一部分。 当我用Notpad ++打开文件时,它总是在文件的一部分之间显示空字节。
线程1写1 线程2写入12 线程3写入123 线程4写入1234
结果如下: 1Nul12Nul123Nul1234Nul
MMF需要2个字节来写“1”字符,但实际上“1”字符只有一个字节。
如果我将1个字节设置为MMF,它将抛出:访问者中没有足够的字节来写入此位置。
如何删除这些空字节?
更新代码: 我只使用2个线程以便于查看。
static void Main(string[] args)
{
File.Delete(@"C:\abc.txt");
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken cancellationToken = tokenSource.Token;
// Write data to file using MMF.
Task<int>[] tasks = new Task<int>[2];
tasks[0] = new Task<int>(() => F1(0, 2, "1", cancellationToken), cancellationToken);
tasks[1] = new Task<int>(() => F2(2,4, "12", cancellationToken), cancellationToken);
// Create MMF File.
MemoryMappedFileSecurity CustomSecurity = new MemoryMappedFileSecurity();
MemoryMappedFile MemoryMapped = MemoryMappedFile.CreateFromFile(
new FileStream(@"C:\abc.txt", FileMode.OpenOrCreate),
"MapAbcFile",// Name
20, // Size
MemoryMappedFileAccess.ReadWrite, // Access type
null, // You can customize the security
HandleInheritability.None
, false); // Inherit to child process
try
{
ParallelOptions op = new ParallelOptions();
op.CancellationToken = tokenSource.Token;
Parallel.ForEach(tasks, op, t =>
{
try
{
t.Start();
}
catch (Exception)
{
tokenSource.Cancel();
}
});
// Wait for all the tasks to finish.
Task.WaitAll(tasks, cancellationToken);
Console.WriteLine("Done!");
}
catch (OperationCanceledException)
{
Console.WriteLine("Cancelled!");
}
catch (AggregateException ae)
{
//tokenSource.Cancel();
Console.WriteLine("AggregateException!");
// Assume we know what's going on with this particular exception.
// Rethrow anything else. AggregateException.Handle provides
// another way to express this. See later example.
foreach (var ie in ae.InnerExceptions)
{
Console.WriteLine(ie.Message);
}
}
MemoryMapped.Dispose();
}
private static int F1(long offset, long size, string firstName, CancellationToken cancellationToken)
{
Console.WriteLine(string.Format("ManagedThreadId(F1): {0} - {1}", System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToLongTimeString()));
MemoryMappedFile MemoryMapped = MemoryMappedFile.OpenExisting("MapAbcFile");
MemoryMappedViewAccessor WriteFirstPart = MemoryMapped.CreateViewAccessor(offset, size, MemoryMappedFileAccess.ReadWrite);
int i = 0;
foreach (char item in firstName.ToCharArray())
{
WriteFirstPart.Write(i, item);
i++;
}
WriteFirstPart.Dispose();
return 1;
}
private static int F2(long offset, long size, string lastName, CancellationToken cancellationToken)
{
Console.WriteLine(string.Format("ManagedThreadId(F2): {0} - {1}", System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToLongTimeString()));
MemoryMappedFile MemoryMapped = MemoryMappedFile.OpenExisting("MapAbcFile");
MemoryMappedViewAccessor WriteFirstPart = MemoryMapped.CreateViewAccessor(offset, size, MemoryMappedFileAccess.ReadWrite);
int i = 0;
foreach (char item in lastName.ToCharArray())
{
WriteFirstPart.Write(i, item);
i++;
}
WriteFirstPart.Dispose();
return 1;
}
答案 0 :(得分:2)
你的错误在这里:
但实际上“1”字符只有一个字节。
然而,Char
实际上定义为:
将字符表示为UTF-16代码单元。
UTF-16代码单元占用两个字节。
如果您希望1
只占用一个字节,那么您需要使用System.Text.Encoding
类中的某些东西来使用说ASCII或UTF-8,或者使用其他编码来处理字符{ {1}}占用一个字节。 E.g。
1