-1

我有一些业务逻辑来检查 Web 服务是否存在。

我想在开始时间后的 1 小时内每 5 分钟重复检查一次。

如何通过任务或线程或等待/异步功能来做到这一点。

4

2 回答 2

5

线程解决方案如下所示:

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# 启动计划任务

我更喜欢线程解决方案,因为从外部进程获取数据有点复杂。将线程数据同步到主线程更容易。您将需要通过命名管道或套接字通信 (TCP/UDP)在WCF上的IPC(进程间通信)等范例。

如果您需要提示如何从线程中取回数据:您可以例如在 WebserviceChecker 类中定义一个事件,当您的 WS 状态发生变化时您将触发该事件。

关于IsBackground事情的一些话......如果您不将线程设置为后台,则您的应用程序只会在每个前台线程退出他的工作方法时退出。当应用程序关闭时,后台线程将自动中止。

对 ThreadAbortedException 的一句话:在 .NET 中,我们获得了硬中止线程的特权。框架将在线程方法中的任何位置引发此异常以退出它。如果你没有抓住它,线程将在没有清理的情况下退出。所以只要抓住它,清理内存或做一些整理任务。你会在这里这样做:

_watcher.Abort();

干杯ceth :)

[编辑] 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]

于 2013-03-08T06:51:22.137 回答
1

首先,重新审视您的业务需求。这到底能带给你什么?一个 web 服务随时可能突然消失,所以你刚刚检查它的事实并不意味着你的下一个调用会成功。这适用于所有网络通信。

因此,如果您有一个单独的“检查器”,则不会降低“真实”代码的复杂性。这种设计的唯一好处是向用户提供某种视觉通知,他们可以合理地确定他们对服务的下一次调用将成功。即使这样,您也可能需要重新考虑,因为这只是合理确定,如果您对他们撒谎,用户会生气。

也就是说,您可以Task像这样使用 s 来做到这一点:

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.
于 2013-03-08T13:37:30.567 回答