22

Cancel()my のメソッドを呼び出して次のコンテンツで非同期メソッドをキャンセルすると、CancellationTokenSource最終的に停止します。ただし、行Console.WriteLine(await reader.ReadLineAsync());が完了するまでにかなりの時間がかかるため、呼び出しに対するメソッドの応答性を高めるために、(空の文字列が返されることを期待して) to もCancellationToken渡そうとしました。ただし、 to を渡すことができませんでした。ReadLineAsync()Cancel()CancellationTokenReadLineAsync()

Console.WriteLine()orへの通話をキャンセルできますか? キャンセルできるStreamreader.ReadLineAsync()場合、どうすればよいですか?

ReadLineAsync()が受け入れないのはなぜCancellationTokenですか? CancellationTokenメソッドがキャンセルされた後も完了する場合でも、非同期メソッドにオプションのパラメーターを与えることをお勧めします。

StreamReader reader = new StreamReader(dataStream);
while (!reader.EndOfStream)
{
    if (ct.IsCancellationRequested){
        ct.ThrowIfCancellationRequested();
        break;
    }
    else
    {
        Console.WriteLine(await reader.ReadLineAsync());
    }
}

更新: 以下のコメントに記載されているように、Console.WriteLine()1 行あたり 40.000 文字の不適切な形式の入力文字列が原因で、呼び出しだけですでに数秒かかっていました。これを分解すると応答時間の問題は解決しますが、何らかの理由で 40.000 文字を 1 行に書き込むことが意図されていた場合 (たとえば、文字列全体をファイル)。

4

5 に答える 5

3

私はこれに対するこの答えを一般化しました:

public static async Task<T> WithCancellation<T>(this Task<T> task, CancellationToken cancellationToken, Action action, bool useSynchronizationContext = true)
{
    using (cancellationToken.Register(action, useSynchronizationContext))
    {
        try
        {
            return await task;
        }
        catch (Exception ex)
        {

            if (cancellationToken.IsCancellationRequested)
            {
                // the Exception will be available as Exception.InnerException
                throw new OperationCanceledException(ex.Message, ex, cancellationToken);
            }

            // cancellation hasn't been requested, rethrow the original Exception
            throw;
        }
    }
}

これで、キャンセル可能な非同期メソッドでキャンセル トークンを使用できるようになりました。たとえば、WebRequest.GetResponseAsync:

var request = (HttpWebRequest)WebRequest.Create(url);

using (var response = await request.GetResponseAsync())
{
    . . .
}

となります:

var request = (HttpWebRequest)WebRequest.Create(url);

using (WebResponse response = await request.GetResponseAsync().WithCancellation(CancellationToken.None, request.Abort, true))
{
    . . .
}

例を参照してくださいhttp://pastebin.com/KauKE0rW

于 2016-10-13T19:59:39.580 に答える