0

次の基本的なワークフローを実行するサービスがあります。

1) 開始し、構成設定を読み取り、大規模なループでいくつかの計算を実行します。

2) ループの反復ごとに、サービスが停止するように指示されているかどうかを確認できる必要があります。データベースのフェッチ、計算を実行し、結果を保存します。コードが SQL トランザクションに関してどれだけうまく機能しているかについては確信が持てないため、この段階では、各反復の開始時にサービス停止をチェックするだけであると仮定して喜んでいます。

3) すべての反復を実行した後、サービスは一定期間「スリープ」します。5分でもいい。12時間かもしれません。このスリープ期間中に「停止」できる必要があります。

現在、これは以下によって実行されます。

private int threadSleepMinutes = 60;

private readonly Mutex mutTerminateService = new Mutex(false);

private Thread serviceThread;

private Thread serviceStopThread;

// Use this flag to allow the Start op to wait for serviceStopThread
// to get going before continuing to create the main loop thread
private volatile bool stopService = true;

public void Start()
{
    this.serviceStopThread = new Thread(this.RunServiceStopThread);
    this.serviceStopThread.IsBackground = true;
    this.serviceStopThread.Start();

    while (stopService)
    {
        Thread.Sleep(100);
    }

    // Some things renamed to anonymise... you get the idea!
    this.serviceThread = new Thread(this.BigLoopMethod);
    this.serviceThread.IsBackground = true;
    this.serviceThread.Start();
}

public void Stop()
{
    // Release the mutex to terminate the service
    serviceStopThread.Resume();

    // Wait 5s max
    int timeout = 5000;
    while (this.serviceThread.IsAlive && timeout > 0)
    {
        Thread.Sleep(100);
        timeout -= 100;
    }
}

private void RunServiceStopThread()
{
    // To guarantee the same thread takes the mutex
    // and releases it in dot net 4, do both ops in this single thread!
    // Dot net 4 the Start() and Stop() are now usually on different threads.
    mutTerminateService.WaitOne();
    stopService = false;

    // Suspend ourself
    serviceStopThread.Suspend();

    // Release the mutex
    mutTerminateService.ReleaseMutex();
}

public void BigLoopMethod()
{
    try
    {
      do
      {
          bool moreOperationsToGo = true; // Just dummy flags and 'stuff' methods here
          while (moreOperationsToGo && !mutTerminateService.WaitOne(0))
          {
              DoStuff();
          }

          // Using this mutex here to sleep nicely - event driven.
          // Gracefully continues after timeout and gracefully exits if 
          // triggered by the mutex.
      }
      while (!mutTerminateService.WaitOne(this.threadSleepMinutes * 60000));
    }
    catch (Exception ex)
    {
        // Exception handling & logging here
    }
}

Suspend と Resume は非推奨であるというメッセージが表示されるようになりました。私の状況では、呼び出し自体が中断されたものであるため、中断が実行されたコードを正確に知っています! 再開、私はそれが何をしようとしているのかを正確に知っています。そもそもこれが行われた唯一の理由は、ミューテックスが dot net 3.5 の Start() と Stop() で正常に機能したが、dot net 4.0 が変更され、Start() と Stop() が異なるスレッドにあり、それらがマークされたためです。回避策は時代遅れです!

これを行うための良い方法、時代遅れでない方法はありますか?

ありがとう

4

2 に答える 2

0

「停止」スレッドは必要ありません。start メソッドが をトリガーするという事実でBigLoopMethod十分です。停止に必要なのは、ミューテックスにシグナルを送ってから、適切なタイムアウトでスレッドに参加することです (Thread.Join() はスレッドが停止するのを待ちます)。スレッドが適切な時間内に参加してサービスを強制終了しない場合は、スレッドを中止する堅牢性をお勧めします。

したがって、疑似コードでは次のようになります。

void Start() 
{
    OpenMutex();
    TakeMutex();
    KickOffMyThread();
}

void Stop();
{
    SignalMutex();
    if (!MyThread.Join(Timeout))
    {
        MyThread.Abort();
        Environment.Exit(1); // Die as thread won't join
    }
}

void MyThread()
{
    while (!TakeMutex(sleeptime)
    {
        DoLongWork();
    }
    //Thread was signalled, exiting.
}
于 2013-05-20T02:23:12.873 に答える