无尽任务的最佳方式

时间:2017-08-30 11:26:51

标签: c# task

我有一个任务outputTask。该任务读取StreamReader(带StreamReader.ReadLineAsync()),

的输出

它只能以这种方式运作:

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);
};

它的作用是肯定的,但还有另一种方法可以让它变得更好吗?

修改:现在看起来就是这样

// ...
Task.Factory.StartNew(() => readUntilEnd(plinkInstance.StandardOutput, timer, cancel.Token), cancel.Token);
// ...

方法

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);
    }
}

为什么我需要CancellationToken?我也可以传递一个bool-object?

2 个答案:

答案 0 :(得分:2)

由于您以异步方式运行连续任务,为什么不让它成为无限循环呢?

Task.Run(() =>
         {
            while (true)
            {
               var output = await READ_LINE_ASYNCHRONOUSLY();
               _outputLines.Add(output);
            }
         });

如果你需要一些方法来摆脱你的循环(我假设你可能),请使用CancellationToken,例如,这里:

How to cancel a Task in await?

编辑:这里有完整的代码,你可能想做什么:

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]);
    }
}

答案 1 :(得分: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);
    }

}