Help us understand the problem. What is going on with this article?

C# 非同期メソッドのタイムアウト

More than 1 year has passed since last update.

非同期メソッドのタイムアウトをさせたかったのでコード試してみた。

最初は、Task.Wait() を使用しようとしたけど、結局Task.Result で待ち合わせるので、結局待ち合わせてしまう。Task.WhenAny を使えばうまくいく。Task.WhenAny は複数のタスクのうち、どれかが終われば、先に進むタスク。その性質を利用している。

自分用のメモ

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace PollingSpike
{
    class Program
    {
        static void Main(string[] args)
        {
            new Program().MainAsync().GetAwaiter().GetResult();
        }

        private async Task MainAsync()
        {
            var timeout = TimeSpan.FromSeconds(5);

            Console.WriteLine($"Timeout: {timeout.TotalMilliseconds}");
            var task = pollingMessageAsync();
            if (await Task.WhenAny(task, Task.Delay(timeout)) == task)
            {
                Console.WriteLine($"Result: {task.Result.ToString()}");
            } else
            {
                Console.WriteLine("Result1 timeout");
            }
            var task2 = pollingMessageTimeOutAsync();
            if (await Task.WhenAny(task2, Task.Delay(timeout)) == task2)
            {
                Console.WriteLine($"Result2: {task2.Result.ToString()}");
            } else
            {
                Console.WriteLine("Result2 timeout");
            }
            Console.ReadLine();
            Console.WriteLine("Task3 has been started");
            var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
            var token = cts.Token;
            try
            {
                var task3 = await pollingMEssageTimeOutByCancellationToken(token);
                Console.WriteLine($"Result3 this is not called {task3}");

            } catch (TaskCanceledException e)
            {
                Console.WriteLine($"Task3 has been canceled by timeout {e.Message}");
                Console.ReadLine();
            } 
        }

        private async Task<string> pollingMessageAsync()
        {
            await Task.Delay(TimeSpan.FromSeconds(3));
            return "Finish! 3 sec";
        }

        private async Task<string> pollingMessageTimeOutAsync()
        {
            await Task.Delay(TimeSpan.FromSeconds(10));
            return "Finish! 10 sec";

        }

        private async Task<string> pollingMEssageTimeOutByCancellationToken(CancellationToken token)
        {
            await Task.Delay(TimeSpan.FromSeconds(10), token);
            return "Finish! 10 sec with cancellation token";
        }
    }
}


追記 2017/12/31 17:20

Cancellation token がよさげということなので、そのパターンも実装してみました。普通のインターフェイスも実装しているから
それがいいのかな。ちなみに、Cancellation Token を実装すると、メソッド側で、Cancellation token が呼ばれたかをチェックする必要がありますが、今回はループ系で使うのでそれでいいのかもですね。ご指摘いただきありがとうございました。

Resource

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away