Выполнение метода по таймеру внутри пула потоков - PullRequest
2 голосов
/ 07 июля 2011

В моем многопоточном веб-приложении я вызываю ThreadPool SomeMethod, который может вызвать исключение.Предположим, я хочу сделать несколько попыток, если это вызовет исключение при первом вызове.Я решаю использовать System.Timers.Timer внутри моего действия для попыток.Могу ли я использовать код ниже?Это безопасно?

static void Caller()
{
    ThreadPool.QueueUserWorkItem(action =>
        {
            try
            {
                SomeMethod();
                Console.WriteLine("Done.");
            }
            catch
            {
                var t = new System.Timers.Timer(1000);
                t.Start();
                var count = 0;
                t.Elapsed += new System.Timers.ElapsedEventHandler((o, a) =>
                {
                    var timer = o as System.Timers.Timer;
                    count++;
                    var done = false;
                    Exception exception = null;
                    try
                    {
                        Console.WriteLine(count);
                        SomeMethod();
                        done = true;
                    }
                    catch (Exception ex)
                    {
                        exception = ex;
                    }
                    if (done || count == 10)
                    {
                        Console.WriteLine(String.Format("Stopped. done: {0}, count: {1}", done, count));
                        t.Stop();
                        if (!done) throw exception;
                    }
                });
            }
        });
    Thread.Sleep(100000);
}

static void SomeMethod()
{
    var x = 1 / new Random().Next(0, 2);
}

Ответы [ 3 ]

2 голосов
/ 07 июля 2011

Вы должны утилизировать каждый Timer после использования, это точно. Но, возможно, вы могли бы сделать что-то еще проще:

static void Main()
{
    ThreadPool.QueueUserWorkItem(action =>
    {
        while (TrySomeMethod() == false)
            Thread.Sleep(1000);
    });

    // wait here
    Console.Read();
}

static bool TrySomeMethod()
{
    try
    {
         SomeMethod();
         return true;
    }
    catch
    {
         return false;
    }
}
1 голос
/ 07 июля 2011

Я не думаю, что использование таймера в потоке потоков является безопасным подходом.Я могу ошибаться, но таймер поднимет свое истекшее событие, когда метод потока уже завершен для выполнения.В этом случае будет сгенерировано исключение.Кроме того, я не вижу, чтобы вы не использовали таймер, что приводит к утечке ресурсов.Если вы объясните, зачем вам нужен таймер, я постараюсь найти безопасное решение ...

0 голосов
/ 07 июля 2011

Я не вижу смысла использовать Timer в очереди ThreadPool, потому что ThreadPool будет порождать новый поток, а Timer также будет порождать новый поток.

Я бы просто создал цикл внутри этого делегата, потому что он не заблокировал бы основной поток в любом случае.Груо показал хороший пример этого.

...