C# 完成无止境任务的最佳方式
我有一个任务C# 完成无止境任务的最佳方式,c#,task,C#,Task,我有一个任务输出任务。任务读取StreamReader(使用StreamReader.readlinesync())的输出 它仅以这种方式工作: var outputTask = plinkInstance.StandardOutput.ReadLineAsync().ContinueWith(hasOutputReaded); Action<Task<string>> hasOutputReaded = null; hasOutputReaded = (previou
输出任务。任务读取StreamReader
(使用StreamReader.readlinesync()
)的输出
它仅以这种方式工作:
var outputTask = plinkInstance.StandardOutput.ReadLineAsync().ContinueWith(hasOutputReaded);
Action<Task<string>> hasOutputReaded = null;
hasOutputReaded = (previousTask) =>
{
resetTimer.Invoke();
_outputLines.Add(previousTask.Result);
previousTask = plinkInstance.StandardOutput.ReadLineAsync();
previousTask.ContinueWith(hasOutputReaded);
};
方法呢
private static void readUntilEnd(StreamReader stream, System.Timers.Timer timer, CancellationToken canelToken)
{
char[] buffer = new char[1];
stream.ReadAsync(buffer, 0, 1);
int cooldown = 0;
while (!canelToken.IsCancellationRequested)
{
if (buffer[0] != '\0')
{
readAChar(buffer[0]);
buffer[0] = '\0';
stream.ReadAsync(buffer, 0, 1);
timer.Stop();
timer.Start();
cooldown = 0;
}
else
{
if (cooldown < 100)
cooldown++;
}
if (cooldown > 0)
Thread.Sleep(cooldown);
}
}
private static void readUntilEnd(StreamReader stream、System.Timers.Timer Timer、CancellationToken canelToken)
{
char[]buffer=新字符[1];
ReadAsync(缓冲区,0,1);
int冷却时间=0;
而(!canelToken.iscancellationrequest)
{
如果(缓冲区[0]!='\0')
{
readAChar(缓冲区[0]);
缓冲区[0]='\0';
ReadAsync(缓冲区,0,1);
timer.Stop();
timer.Start();
冷却时间=0;
}
其他的
{
如果(冷却时间<100)
冷却++;
}
如果(冷却时间>0)
线程。睡眠(冷却);
}
}
为什么我需要取消令牌
?我还可以传递bool对象,或者不传递?既然您正在异步运行连续任务,为什么不让它成为一个无休止的循环呢
Task.Run(() =>
{
while (true)
{
var output = await READ_LINE_ASYNCHRONOUSLY();
_outputLines.Add(output);
}
});
如果您需要某种方法来打破循环(我想您可能需要),请使用CancellationToken
,如下所述:
编辑:以下是执行您可能希望执行的操作的完整代码:
Task.Run(() => ReadUntilEnd(streamReader, cancellationTokenSource.Token),
cancellationTokenSource.Token);
//...
private static async Task ReadUntilEnd(StreamReader streamReader,
CancellationToken cancellationToken)
{
char[] buffer = new char[1];
while (!cancellationToken.IsCancellationRequested)
{
await streamReader.ReadAsync(buffer, 0, 1);
readAChar(buffer[0]);
}
}
private static async Task readUntilEnd(StreamReader stream,System.Timers.Timer Timer,CancellationToken canelToken)
{
char[]buffer=新字符[1];
Task readTask=stream.ReadAsync(缓冲区,0,1);
int冷却时间=5;
而(!canelToken.iscancellationrequest)
{
如果(readTask.IsCompleted)
{
readAChar(缓冲区[0]);
缓冲区[0]='\0';
readTask=stream.ReadAsync(缓冲区,0,1);
timer.Stop();
timer.Start();
冷却时间=0;
}
其他的
{
如果(冷却时间<100)
冷却++;
}
如果(冷却时间>0)
等待任务。延迟(冷却,canelToken);
}
}
任务(在我第一次尝试时)是一个局部变量。所以垃圾收集器停止了循环(我猜)。但是在这里我必须写一个额外的取消。不,GC不会停止你的循环,因为你的任务一直在引用它自己,所以它对于垃圾收集是不可行的。只要你的应用程序(或者线程,如果你正在做更复杂的事情)在运行,它就会一直运行。我还简化了我的示例——如果出于某种原因,您希望有一个变量,而不是内联提供Task.Run()参数,那么您可以这样做。但对于如何以及何时终止任务,它仍然无能为力。新方法更好吗?(看第一篇帖子)@user6537157是的,因为它是我上面写的通用版本的一个具体实现。否,因为您在不等待结果的情况下启动异步方法(ReadAsync
),但仍在尝试使用结果(通过访问缓冲区
变量)。睡前阅读:,但简短的版本是:1。使您的readUntilEnd
方法异步任务
(而不是void
)2。在每次调用ReadAsync
@user6537157之前添加wait
关键字。您的代码的一个重要问题是,它不会以确定的方式工作-有时它甚至可以正常工作,但有时它会漏掉一些行并读取同一行两次,因为您的代码是如何独立于流读取部分进行的。
Task.Run(() => ReadUntilEnd(streamReader, cancellationTokenSource.Token),
cancellationTokenSource.Token);
//...
private static async Task ReadUntilEnd(StreamReader streamReader,
CancellationToken cancellationToken)
{
char[] buffer = new char[1];
while (!cancellationToken.IsCancellationRequested)
{
await streamReader.ReadAsync(buffer, 0, 1);
readAChar(buffer[0]);
}
}
private static async Task readUntilEnd(StreamReader stream, System.Timers.Timer timer, CancellationToken canelToken)
{
char[] buffer = new char[1];
Task readTask = stream.ReadAsync(buffer, 0, 1);
int cooldown = 5;
while (!canelToken.IsCancellationRequested)
{
if (readTask.IsCompleted)
{
readAChar(buffer[0]);
buffer[0] = '\0';
readTask = stream.ReadAsync(buffer, 0, 1);
timer.Stop();
timer.Start();
cooldown = 0;
}
else
{
if (cooldown < 100)
cooldown++;
}
if (cooldown > 0)
await Task.Delay(cooldown, canelToken);
}
}