16

私はC#が初めてです。私は主にJavaをやっていました。

次のようなタイムアウトを実装したいと思います。

int now= Time.now();
while(true)
{
  tryMethod();
  if(now > now+5000) throw new TimeoutException();
}

これをC#で実装するにはどうすればよいですか? ありがとう!

4

7 に答える 7

40

考えられる方法の1つは次のとおりです。

Stopwatch sw = new Stopwatch();
sw.Start();

while(true)
{
    tryMethod();
    if(sw.ElapsedMilliseconds > 5000) throw new TimeoutException();
}

ただし、現在、ループから抜け出す方法はありません。をtryMethod返して、次のboolように変更することをお勧めします。

Stopwatch sw = new Stopwatch();
sw.Start();

while(!tryMethod())
{
    if(sw.ElapsedMilliseconds > 5000) throw new TimeoutException();
}
于 2012-04-13T15:44:26.170 に答える
6

タイマーとデリゲートを使用してこれを行うことができると思います。私のコード例は次のとおりです。

using System;
using System.Timers;

class Program
{
    public delegate void tm();

    static void Main(string[] args)
    {
        var t = new tm(tryMethod);
        var timer = new Timer();
        timer.Interval = 5000;

        timer.Start();

        timer.Elapsed += (sender, e) => timer_Elapsed(t);
        t.BeginInvoke(null, null);
    }

    static void timer_Elapsed(tm p)
    {
        p.EndInvoke(null);
        throw new TimeoutException();
    }

    static void tryMethod()
    {
        Console.WriteLine("FooBar");
    }
}

tryMethod があり、次にデリゲートを作成し、このデリゲートを tryMethod に向けてから、このデリゲートを非同期的に開始します。次に、間隔が5000ミリ秒のタイマーがあり、デリゲートをタイマー経過メソッドに渡します(デリゲートは値型ではなく参照型であるため、これは機能するはずです)。5000秒が経過したら、EndInvokeを呼び出しますデリゲートのメソッド。

于 2012-04-13T15:59:44.710 に答える
4

tryMethod() がブロックしない限り、これはあなたが望むことをするはずです:

モバイルの場合、夏時間やタイムゾーンの変更には安全ではありません:

DateTime startTime = DateTime.Now;

while(true)
{
    tryMethod();
    if(DateTime.Now.Subtract(startTime).TotalMilliseconds > 5000)
        throw new TimeoutException();
}

タイムゾーンと夏時間セーフ バージョン:

DateTime startTime = DateTime.UtcNow;

while(true)
{
    tryMethod();
    if(DateTime.UtcNow.Subtract(startTime).TotalMilliseconds > 5000)
        throw new TimeoutException();
} 

(DateTimeOffset には .NET 3.5 以降が必要です。)

DateTimeOffset startTime = DateTimeOffset.Now;

while(true)
{
    tryMethod();
    if(DateTimeOffset.Now.Subtract(startTime).TotalMilliseconds > 5000)
        throw new TimeoutException();
} 
于 2012-04-13T16:06:56.490 に答える
1

私がやりたい別の方法:

public class TimeoutAction
    {
        private Thread ActionThread { get; set; }
        private Thread TimeoutThread { get; set; }
        private AutoResetEvent ThreadSynchronizer { get; set; }
        private bool _success;
        private bool _timout;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="waitLimit">in ms</param>
        /// <param name="action">delegate action</param>
        public TimeoutAction(int waitLimit, Action action)
        {
            ThreadSynchronizer = new AutoResetEvent(false);
            ActionThread = new Thread(new ThreadStart(delegate
            {
                action.Invoke();
                if (_timout) return;
                _timout = true;
                _success = true;
                ThreadSynchronizer.Set();
            }));

            TimeoutThread = new Thread(new ThreadStart(delegate
            {
                Thread.Sleep(waitLimit);
                if (_success) return;
                _timout = true;
                _success = false;
                ThreadSynchronizer.Set();
            }));
        }

        /// <summary>
        /// If the action takes longer than the wait limit, this will throw a TimeoutException
        /// </summary>
        public void Start()
        {
            ActionThread.Start();
            TimeoutThread.Start();

            ThreadSynchronizer.WaitOne();

            if (!_success)
            {
                throw new TimeoutException();
            }
            ThreadSynchronizer.Close();
        }
    }
于 2014-03-05T19:22:33.427 に答える