如何使用 StreamWriter 避免竞争条件
How to Avoid Race Condition using StreamWriter
根据:https://msdn.microsoft.com/en-us/library/system.io.streamwriter%28v=vs.110%29.aspx,"By default, a StreamWriter is not thread safe. See TextWriter.Synchronized for a thread-safe wrapper." 所以我写了一个方法并使用 TextWriter.Synchronized 来同步我的 StreamWriter 对象:
static void GenerateData()
{
string fileName = Path.Combine(directory, "filenames.txt");
using(StreamWriter names = new StreamWriter(fileName))
{
// Synchronize access to names
TextWriter.Synchronized(names);
// Create 100,000 test files
// Take advantage of parallelism
Parallel.For(0, 100001, i =>
{
// Generate name of test file
string curFile = Path.Combine(directory, String.Format("test{0}.txt", i + 1));
// Store test file name in filenames.txt
names.WriteLine(curFile);
using(StreamWriter writer = new StreamWriter(curFile))
{
// Take advantage of multiple cores
//TextWriter.Synchronized(writer);
// For 30 lines ..
for(int j = 0; j < 30; j++)
{
List<Rule> rules = new List<Rule>();
// .. generate i rules
for(int k = 0; k < i; k++)
{
// Name of rule starts with r followed by random number in range [0, 9999]
string name = "r" + String.Format("{0}", random.Next(0, 10000));
// Rule priority is in range [0, 500]
int pty = random.Next(1, 501);
rules.Add(new Rule(name, pty));
}
// Write the list of rules to curFile
writer.WriteLine(String.Join(", ", rules.ToArray()));
};
}
});
}
}
然而,尽管如此,输出文件 (filenames.txt) 中的某些行仍然与其他行混在一起。我想知道是否可以在不锁定 StreamWriter 的情况下解决这个问题。
示例输出:
- C:\Users\Frank\Documents\visual工作室2013\Projects\TimedAssignment3\TimedAssignment3\Datasets\test1.txt
- C:\Users\Frank\Documents\visual工作室2013\Projects\TimedAssignment3\TimedAssignment3\Datasets\test50001.txt
- C:\Users\Frank\Documents\visual工作室2013\Projects\TimedAssignment3\TimedAssignment3\Datasets\tesal工作室2013\Projects\TimedAssignment3\TimedAssignment3\Datasets\test37501.txt
- C:\Users\Frank\Documents\visual工作室2013\Projects\TimedAssignment3\TimedAssignment3\Datasets\test87501.txt
- C:\Users\Frank\Documents\visual工作室2013\Projects\TimedAssignment3\TimedAssignment3\Datasets\test12501.txt
像这样使用返回的 TextWriter
:
var syncWriter = TextWriter.Synchronized(names);
MSDN(https://msdn.microsoft.com/en-us/library/system.io.textwriter.synchronized(v=vs.110).aspx) 说:
All write operations to the returned wrapper will be thread safe. You
call this method to ensure that only one thread at a time can execute
the methods on the TextWriter instance that is returned.
Synchronized()
不会创建实例 'synchronized' 但 returns 新的同步实例。
根据:https://msdn.microsoft.com/en-us/library/system.io.streamwriter%28v=vs.110%29.aspx,"By default, a StreamWriter is not thread safe. See TextWriter.Synchronized for a thread-safe wrapper." 所以我写了一个方法并使用 TextWriter.Synchronized 来同步我的 StreamWriter 对象:
static void GenerateData()
{
string fileName = Path.Combine(directory, "filenames.txt");
using(StreamWriter names = new StreamWriter(fileName))
{
// Synchronize access to names
TextWriter.Synchronized(names);
// Create 100,000 test files
// Take advantage of parallelism
Parallel.For(0, 100001, i =>
{
// Generate name of test file
string curFile = Path.Combine(directory, String.Format("test{0}.txt", i + 1));
// Store test file name in filenames.txt
names.WriteLine(curFile);
using(StreamWriter writer = new StreamWriter(curFile))
{
// Take advantage of multiple cores
//TextWriter.Synchronized(writer);
// For 30 lines ..
for(int j = 0; j < 30; j++)
{
List<Rule> rules = new List<Rule>();
// .. generate i rules
for(int k = 0; k < i; k++)
{
// Name of rule starts with r followed by random number in range [0, 9999]
string name = "r" + String.Format("{0}", random.Next(0, 10000));
// Rule priority is in range [0, 500]
int pty = random.Next(1, 501);
rules.Add(new Rule(name, pty));
}
// Write the list of rules to curFile
writer.WriteLine(String.Join(", ", rules.ToArray()));
};
}
});
}
}
然而,尽管如此,输出文件 (filenames.txt) 中的某些行仍然与其他行混在一起。我想知道是否可以在不锁定 StreamWriter 的情况下解决这个问题。
示例输出:
- C:\Users\Frank\Documents\visual工作室2013\Projects\TimedAssignment3\TimedAssignment3\Datasets\test1.txt
- C:\Users\Frank\Documents\visual工作室2013\Projects\TimedAssignment3\TimedAssignment3\Datasets\test50001.txt
- C:\Users\Frank\Documents\visual工作室2013\Projects\TimedAssignment3\TimedAssignment3\Datasets\tesal工作室2013\Projects\TimedAssignment3\TimedAssignment3\Datasets\test37501.txt
- C:\Users\Frank\Documents\visual工作室2013\Projects\TimedAssignment3\TimedAssignment3\Datasets\test87501.txt
- C:\Users\Frank\Documents\visual工作室2013\Projects\TimedAssignment3\TimedAssignment3\Datasets\test12501.txt
像这样使用返回的 TextWriter
:
var syncWriter = TextWriter.Synchronized(names);
MSDN(https://msdn.microsoft.com/en-us/library/system.io.textwriter.synchronized(v=vs.110).aspx) 说:
All write operations to the returned wrapper will be thread safe. You call this method to ensure that only one thread at a time can execute the methods on the TextWriter instance that is returned.
Synchronized()
不会创建实例 'synchronized' 但 returns 新的同步实例。