9

I'm just starting out with C#'s new async features. I've read plenty of how-to's now on parallel downloads etc. but nothing on reading/processing a text file.

I had an old script I use to filter a log file and figured I'd have a go at upgrading it. However I'm unsure if my usage of the new async/await syntax is correct.

In my head I see this reading the file line by line and passing it on for processing in different thread so it can continue without waiting for a result.

Am I thinking about it correctly, or what is the best way to implement this?

static async Task<string[]> FilterLogFile(string fileLocation)
{
    string line;

    List<string> matches = new List<string>();

    using(TextReader file = File.OpenText(fileLocation))
    {        
        while((line = await file.ReadLineAsync()) != null)
        {
            CheckForMatch(line, matches);
        }
    }

    return matches.ToArray();
}

The full script: http://share.linqpad.net/29kgbe.linq

4

1 に答える 1

9

私の頭の中で、これがファイルを1行ずつ読み取り、別のスレッドで処理するために渡すので、結果を待たずに続行できることがわかります。

しかし、それはあなたのコードが行うことではありません。代わりに、すべての読み取りが完了すると、(非同期で)配列を返します。実際に一致を1つずつ非同期で返したい場合は、ある種の非同期コレクションが必要になります。そのためにTPLデータフローのブロックを使用できます。例えば:

ISourceBlock<string> FilterLogFile(string fileLocation)
{
    var block = new BufferBlock<string>();

    Task.Run(async () =>
    {
        string line;

        using(TextReader file = File.OpenText(fileLocation))
        {        
            while((line = await file.ReadLineAsync()) != null)
            {
                var match = GetMatch(line);

                if (match != null)
                    block.Post(match);
            }
        }

        block.Complete();
    });

    return block;
}

(おそらく、返されたブロックに障害が発生することにより、エラー処理を追加する必要があります。)

次に、返されたブロックを、結果を処理する別のブロックにリンクします。または、(を使用して)ブロックから直接読み取ることもできますReceiveAsync()


しかし、完全なコードを見ると、このアプローチがあなたにとってそれほど役立つかどうかはわかりません。結果を処理する方法(グループ化してから、各グループでカウント順に並べ替える)のため、すべてを取得するまで、結果を処理することはできません。

于 2013-02-11T13:01:22.627 に答える