给定一种写入文本文件的方法
public void WriteToFile( ) {
var file = "C:\\AsyncTest.txt";
var writer = File.Exists( file ) ? File.AppendText( file ) : File.CreateText( file );
writer.WriteLine( "A simulated entry" );
writer.Close();
}
Run Code Online (Sandbox Code Playgroud)
我需要模拟一个场景,在这个场景中,可以在循环中调用此方法,可能需要几十次,并且必须异步运行.
所以我尝试在一个新的线程中调用该方法(其中writer是WriteToFile所在的类)
//in a loop...
Thread thread = new Thread( writer.WriteToFile );
thread.Start( );
Run Code Online (Sandbox Code Playgroud)
哪个工作完美一次,但抛出了一个IO异常,即在后续迭代中另一个进程正在使用该文件.实际上,这很有道理,但我不知道如何解决它.
我试过像这样使用Join()
Thread thread = new Thread( writer.WriteToFile );
thread.Start( );
thread.Join();
Run Code Online (Sandbox Code Playgroud)
但是这会锁定调用线程,直到所有连接的线程都完成,哪种方式会破坏目的,不是吗?
我尝试使用ThreadPool.QueueUserWorkItem(writer.WriteToFile);,但得到相同的IO异常.
我试过用锁
private object locker = new object();
public void WriteToFile( ) {
lock(locker){
//same code as above
}
}
Run Code Online (Sandbox Code Playgroud)
但这没有明显的效果
我也试过使用Task类无济于事.
那么如何在不冲突的情况下"堆叠"这些后台线程来写入单个文件,而不是锁定调用线程?
Jim*_*hel 11
另一种选择是创建队列.让主线程将字符串放在队列中,并让持久的后台线程读取队列并写入文件.这很容易做到.
private BlockingCollection<string> OutputQueue = new BlockingCollection<string>();
void SomeMethod()
{
var outputTask = Task.Factory.StartNew(() => WriteOutput(outputFilename),
TaskCreationOptions.LongRunning);
OutputQueue.Add("A simulated entry");
OutputQueue.Add("more stuff");
// when the program is done,
// set the queue as complete so the task can exit
OutputQueue.CompleteAdding();
// and wait for the task to finish
outputTask.Wait();
}
void WriteOutput(string fname)
{
using (var strm = File.AppendText(filename))
{
foreach (var s in OutputQueue.GetConsumingEnumerable())
{
strm.WriteLine(s);
// if you want to make sure it's written to disk immediately,
// call Flush. This will slow performance, however.
strm.Flush();
}
}
}
Run Code Online (Sandbox Code Playgroud)
后台线程在输出队列上执行非繁忙等待,因此它不使用CPU资源,除非它实际输出数据.而且因为其他线程只需要在队列中放置一些东西,所以基本上没有等待.
有关更多信息,请参阅我的博客,简单多线程,第2部分.
| 归档时间: |
|
| 查看次数: |
6365 次 |
| 最近记录: |