有没有办法编写一个反复写入数据的异步函数。
编写异步函数
时出现以下错误该进程无法访问文件'c:\ Temp \ Data.txt',因为它正由另一个进程使用
public void GoButton_Click(object sender, System.EventArgs e)
{
IAsyncResult ar = DoSomethingAsync(strURL, strInput);
Session["result"] = ar;
Response.Redirect("wait1.aspx");
}
private IAsyncResult DoSomethingAsync(string strURL, string strInput)
{
DoSomethingDelegate doSomethingDelegate = new DoSomethingDelegate(DoSomething);
IAsyncResult ar = doSomethingDelegate.BeginInvoke(strURL, strInput, new AsyncCallback(MyCallback), null);
return ar;
}
private delegate void DoSomethingDelegate(string strURL, string strInput);
private void MyCallback(IAsyncResult ar)
{
AsyncResult aResult = (AsyncResult)ar;
DoSomethingDelegate doSomethingDelegate = (DoSomethingDelegate)aResult.AsyncDelegate;
doSomethingDelegate.EndInvoke(ar);
}
private void DoSomething(string strURL, string strInput)
{
int i = 0;
for (i = 0; i < 1000; i++)
{
m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine("{0} ", MethodCall(strURL, strInput));
m_streamWriter.Flush();
m_streamWriter.Close();
}
}
答案 0 :(得分:19)
我有同样的问题。现在就解决了。这是一种迟到的建议,但可能对其他人有所帮助。
在下面的控制台示例中包含以下using语句。
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
Use of the FileStream Class
下面的示例使用FileStream类,该类具有导致在操作系统级别发生异步I / O的选项。在许多情况下,这将避免阻塞ThreadPool线程。要启用此选项,必须在构造函数调用中指定useAsync = true或options = FileOptions.Asynchronous参数。
如果您通过指定文件路径直接打开它们,则StreamReader和StreamWriter没有此选项。如果您为它们提供由FileStream类打开的Stream,StreamReader / Writer确实有此选项。请注意,即使线程池线程被阻止,异步也会在UI应用程序中提供响应性优势,因为在等待期间不会阻止UI线程。写文字
以下示例将文本写入文件。在每个await语句中,该方法立即退出。文件I / O完成后,该方法将在await语句后面的语句处继续。请注意,async修饰符位于使用await语句的方法的定义中。
static void Main(string[] args)
{
ProcessWrite().Wait();
Console.Write("Done ");
Console.ReadKey();
}
static Task ProcessWrite()
{
string filePath = @"c:\temp2\temp2.txt";
string text = "Hello World\r\n";
return WriteTextAsync(filePath, text);
}
static async Task WriteTextAsync(string filePath, string text)
{
byte[] encodedText = Encoding.Unicode.GetBytes(text);
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Append, FileAccess.Write, FileShare.None,
bufferSize: 4096, useAsync: true))
{
await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
};
}
阅读文字
以下示例从文件中读取文本。文本是缓冲的,在这种情况下,放在StringBuilder中。与前面的示例不同,await的评估会产生一个值。 ReadAsync方法返回一个Task,因此await的评估会产生一个Int32值(numRead),该值在操作完成后返回。
static void Main(string[] args)
{
ProcessRead().Wait();
Console.Write("Done ");
Console.ReadKey();
}
static async Task ProcessRead()
{
string filePath = @"c:\temp2\temp2.txt";
if (File.Exists(filePath) == false)
{
Console.WriteLine("file not found: " + filePath);
}
else {
try {
string text = await ReadTextAsync(filePath);
Console.WriteLine(text);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
static async Task<string> ReadTextAsync(string filePath)
{
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true))
{
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[0x1000];
int numRead;
while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
string text = Encoding.Unicode.GetString(buffer, 0, numRead);
sb.Append(text);
}
return sb.ToString();
}
}
您可以查看Using Async for File Access
中的原始来源希望有帮助...
答案 1 :(得分:6)
处理异步写入文件的辅助方法示例。
public async Task FileWriteAsync(string filePath, string messaage, bool append = true)
{
using (FileStream stream = new FileStream(filePath, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.None, 4096, true))
using (StreamWriter sw = new StreamWriter(stream))
{
await sw.WriteLineAsync(messaage);
}
}
答案 2 :(得分:5)
异步写入文件无法解决此问题。您需要等待文件可用。
答案 3 :(得分:0)
最终,这取决于你为什么要这样做。
如果您不打算在文件中写入太多数据,可以不断打开和关闭它。
或者,如果您知道何时打开文件以及何时需要关闭文件,可以在需要时打开它,然后保持打开状态直到您知道不再需要它为止。
答案 4 :(得分:0)
如果使用简单的StreamWriter,则可以将其替换为简单的类。无需异步/等待。这是一个编写文本文件的示例。
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Threading.Tasks;
class LogWriter : IDisposable
{
private BlockingCollection<string> blockingCollection = new BlockingCollection<string>();
private StreamWriter log = null;
bool run = true;
Task task = null;
public LogWriter(string logFilePath)
{
log = new StreamWriter(logFilePath);
task = Task.Run(() =>
{
while (run)
{
log.WriteLine(blockingCollection.Take());
}
});
}
public void WriteLine(string value)
{
blockingCollection.Add(value);
}
public void Dispose()
{
run = false;
task.Dispose();
log.Close();
log.Dispose();
}
}
要使用它,就像使用StreamWriter一样:
using (var log = new LogWriter(logFileName))
{
log.WriteLine("Hello world");
// Code here that should not be blocked by writing to the file
}
答案 5 :(得分:0)
简单明了的解决方案:
using var file = new StreamWriter(path);
await file.WriteAsync(content);