Как запустить задачу или поток С# в течение X времени

У меня есть некоторая бизнес-логика, чтобы проверить веб-сервис, жив он или нет.

Я хочу проверять его повторно через каждые 5 минут в течение 1 часа после времени запуска.

Как это сделать с помощью задач, потоков или функций ожидания/асинхронности.


person Abhishek Gupta    schedule 08.03.2013    source источник
comment
Что вы пробовали?   -  person Mario S    schedule 08.03.2013
comment
Ваш заголовок сбивает с толку... Я подозреваю, что вместо этого вы хотите повторять вызов каждые X минут... Проверьте похожие вопросы - stackoverflow.com/questions/tagged/   -  person Alexei Levenkov    schedule 08.03.2013
comment
@Алексей, я точно не хочу делать то, о чем ты думаешь. Я хочу запустить задачу в течение X времени   -  person Abhishek Gupta    schedule 08.03.2013
comment
@ mario до сих пор я просто запускал задачи, которые выполняются бесконечно, пока моя служба Windows не будет запущена, но я хочу запускать эти задачи, скажем, в течение следующих 10 минут. Через 10 минут я должен запускать новые задачи и хочу удалить более ранние   -  person Abhishek Gupta    schedule 08.03.2013
comment
Название до сих пор не ясно для меня, но, по крайней мере, я вижу ваши требования... Я думаю, вам будет трудно найти решение - если вы не хотите работать бесконечно, постоянно проверяя срок действия и не хотите таймеров, это сложно делать что-то спустя какое-то время...   -  person Alexei Levenkov    schedule 08.03.2013


Ответы (2)


Во-первых, пересмотрите свои бизнес-требования. Что именно это дает вам? Веб-сервис может внезапно исчезнуть в любое время, поэтому тот факт, что вы только что проверили его, не означает, что ваш следующий вызов будет успешным. Это верно для всех сетевых коммуникаций.

Так что сложность вашего "реального" кода не уменьшится, если у вас будет отдельная "проверка". Единственным преимуществом такого дизайна является своего рода визуальное уведомление пользователя о том, что он может быть достаточно уверен, что его следующий вызов службы будет успешным. Даже в этом случае вы, возможно, захотите пересмотреть свое решение, потому что это разумно достоверно, и пользователи рассердятся, если вы им солжете.

Тем не менее, вы можете сделать это, используя Tasks следующим образом:

private static async Task CheckAsync(CancellationToken token)
{
  // Check your web service.
  await CheckWebServiceAsync(token);

  // Wait 5 minutes.
  await Task.Delay(TimeSpan.FromMinutes(5), token);
}

...

var done = new CancellationTokenSource(TimeSpan.FromHours(1));
Task checkingTask = CheckAsync(done.Token);
// When checkingTask completes:
//   IsCanceled -> One hour passed with no errors.
//   IsFaulted -> The web service failed.
person Stephen Cleary    schedule 08.03.2013

решение потока выглядит так:

public class WebserviceChecker {

    private int durationInHours = 1;
    public void setDuration(int value) { durationInHours = value; }

    private boolean _shutdown = false;

    private DateTime _startTime = null;
    // System.Windows.Forms.Timer
    private Timer _timer = null;

    public void CheckWebservice() {

        _startTime = DateTime.Now;
        _timer = new Timer();
        _timer.Tick += handleTimerTick;

        while(!_shutdown) {
            try {
                // do what ever you want to do for checking your webservice...
                // ...
            } catch (ThreadAbortedException ex) {
                // do cleanup, then
                //
                break;
            } catch (Exception ex) {
                Logger.Instance.log(LoggerLogType.Type.Err, ex.ToString());
            }
            // wait 5 secs (customize to your needs)
            Threading.Thread.Sleep(5000);
        }

        if(_shutdown) {
            // do some regular cleanup here...
        }

    } // public void CheckWebservice()

    public void Shutdown() {
        _shutdown = true;
    }

    private void handleTimerTick(Object sender, System.EventArgs e) {
        TimeSpan ts = _startTime .Subtract(DateTime.Now);
        if(ts.TotalHours >= durationInHours) {
            Shutdown();
        }
    }
}

а теперь запустите фоновый поток следующим образом:

WebserviceChecker _c = new WebserviceChecker();

Thread _watcher = new Thread(_c.CheckWebservice);
_watcher.IsBackground = true;
_watcher.Start();

для запланированной задачи посмотрите здесь: C# запустить запланированную задачу

я бы предпочел решение с потоком, потому что получение данных из внешнего процесса немного сложнее. синхронизация данных потока с вашим основным потоком проще. вам потребуются такие парадигмы, как IPC (межпроцессное взаимодействие) поверх WCF по именованным каналам или через сокеты ( TCP/UDP).

если вам нужна подсказка, как вернуть данные из вашего потока: вы могли бы, например. определите событие в классе WebserviceChecker, которое вы вызовете при изменении состояния вашего WS.

несколько слов о IsBackground... если вы НЕ переводите поток в фоновый режим, ваше приложение завершится только тогда, когда каждый поток переднего плана выйдет из своего рабочего метода. Фоновые потоки будут автоматически прерваны при закрытии приложения.

слово для ThreadAbortedException: в .NET мы получаем привилегию принудительно прерывать поток. фреймворк вызовет это исключение в любой позиции метода потока, чтобы выйти из него. если вы его не поймаете, поток завершится без очистки. так что просто поймайте его и очистите память или выполните некоторые завершающие задачи. вы бы сделали это вот так:

_watcher.Abort();

ура сет :)

[править] в MSDN есть хороший учебник по многопоточности: http://msdn.microsoft.com/en-us/library/aa645740%28v=vs.71%29.aspx [/edit]

[править] если вы хотите использовать System.Threading.Timer, вам необходимо внедрить делегат System.Threading.TimerCallback в свой класс наблюдателя. то вы можете создать новый таймер с периодом вместо фонового потока. см. http://msdn.microsoft.com/de-de/library/system.threading.timercallback.aspx подробнее [/edit]

person ceth    schedule 08.03.2013
comment
ваш класс Timer относится к system.Threading или system.Timers.Timer - person Abhishek Gupta; 08.03.2013
comment
Система.Windows.Forms.Timer - person ceth; 08.03.2013