1

モノラルで Quartz.net を使用しています。次のようなスケジューラを作成すると:

ISchedulerFactory quartzSchedulerFactory = new StdSchedulerFactory();
IScheduler quartzScheduler = quartzSchedulerFactory.GetScheduler();

Quartz.Net では、クラス SimpleThreadPool で次のメソッドが呼び出されます。

/// <summary>
/// Called by the QuartzScheduler before the <see cref="ThreadPool" /> is
/// used, in order to give the it a chance to Initialize.
/// </summary>
public virtual void Initialize()
{
    if (workers != null && workers.Count > 0) 
    {
        // already initialized...
        return;
    }

    if (count <= 0)
    {
        throw new SchedulerConfigException("Thread count must be > 0");
    }

    // create the worker threads and start them
    foreach (WorkerThread wt in CreateWorkerThreads(count))
    {
        wt.Start();

        availWorkers.AddLast(wt);
    }
}

Windows ではこれで問題なく動作しますが、CentOS では wt.Start() が呼び出されるとシステムがフリーズします。プロセスを強制終了しても、プロセスは機能しなくなり、システムを再起動するだけで強制終了できます。うまくいくこともありますが、約 5 回に 1 回はプログラムを実行します。

WorkerThread の開始時に呼び出されるコードは次のとおりです。

public override void Run()
{
    bool ran = false;
    bool shouldRun;
    lock (this)
    {
        shouldRun = run;
    }

    while (shouldRun)
    {
        try
        {
            lock (this)
            {
                while (runnable == null && run)
                {
                    Monitor.Wait(this, 500);
                }

                if (runnable != null)
                {
                    ran = true;
                    runnable.Run();
                }
            }
        }
        catch (Exception exceptionInRunnable)
        {
            log.Error("Error while executing the Runnable: ", exceptionInRunnable);
        }
        finally
        {
            lock (this)
            {
                runnable = null;
            }
            // repair the thread in case the runnable mucked it up...
            if (Priority != tp.ThreadPriority)
            {
                Priority = tp.ThreadPriority;
            }

            if (runOnce)
            {
                lock (this)
                {
                    run = false;
                }
                tp.ClearFromBusyWorkersList(this);
            }
            else if (ran)
            {
                ran = false;
                tp.MakeAvailable(this);
            }
        }

        // read value of run within synchronized block to be 
        // sure of its value
        lock (this)
        {
            shouldRun = run;
        }
    }

    log.Debug("WorkerThread is shut down");
}

デッドロックの問題でしょうか?もしそうなら、なぜWindowsでは起こらないのですか?

ありがとう

4

1 に答える 1

3

CentOでも同様の問題がありました。Mono 2.10.8.1 は、デフォルトのスレッドプール スレッドの作成でスタックしていました。立ち往生した後、プロセスを強制終了したり、スタックトレースを取得したりすることはできませんでした。

OSのコアを更新することで問題を解決できました。2.6.32-71.el6.x86_64 から 2.6.32-279.14.1.el6.x86_64 まで。

于 2012-12-11T03:02:25.120 に答える