0

C# で Windows サービスを作成しています。その目的は、インターネット上のフィードからの情報を消費することです。zeromq の pub/sub アーキテクチャを使用してデータを取得します (私のサービスはサブスクライバーのみです)。サービスをデバッグするには、WPF コントロール パネルで「ホスト」します。これにより、サービスをインストールしなくても、サービスを開始、実行、および停止できます。私が見ている問題は、停止メソッドを呼び出すと、サービスがデータベースへの書き込みを続けているように見えることです。Debug.WriteLine()書き込みが発生する場所に a を配置したため、これを知っています。

サービスの詳細:

データベースに非同期で書き込むことができるようにサービスを構築しようとしています。これは、スレッドと ThreadPool の組み合わせを使用して実現されます。

public void StartDataReceiver() // Entry point to service from WPF host
{
    // setup zmq subscriber socket

    receiverThread = new Tread(SpawnReceivers);
    receiverThread.Start();
}

internal void SpawnReceivers()
{
    while(!stopEvent.WaitOne(0))
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessReceivedData), subscriber.Recv()); // subscriber.Recv() blocks when there is no data to receive (according to the zmq docs) so this loop should remain under control, and threads only created in the pool when there is data to process.
    }
}

internal void ProcessReceivedData(Object recvdData)
{
    // cast recvdData from object -> byte[]
    // convert byte[] -> JSON string
    // deserialize JSON -> MyData

    using (MyDataEntities context = new MyDataEntities())
    {
        // build up EF model object

        Debug.WriteLine("Write obj to db...");
        context.MyDatas.Add(myEFModel);
        context.SaveChanges();
    }
}

internal void QData(Object recvdData)
{
    Debug.WriteLine("Queued obj in queue...");
    q.Enqueue((byte[])recvdData);
}

public void StopDataReceiver()
{
    stopEvent.Set();
    receiverThread.Join();
    subscriber.Dispose();
    zmqContext.Dispose();
    stopEvent.Reset();
}

上記のコードは、私が懸念しているメソッドです。WPF ホストをデバッグし、メソッドProcessReceivedDataをスレッド プールのキューに入れるように設定すると、StopDataReceiver. 私が知る限り、スレッド プールはこれ以上スレッドをキューに入れません (その行にブレーク ポイントを配置して確認しました) が、出力ウィンドウに "Write obj to db..." が引き続き表示され、' Break All' デバッガーで小さな緑色の矢印がcontext.SaveChanges();行に表示され、実行が現在停止されている場所を示します。さらにテストして、スレッドプールをメソッドのキューに入れると、QDataすべてが期待どおりに機能するようです。サービスを停止するまで、出力ウィンドウに「Queued obj in queue...」というメッセージが表示されます。

TL;DR:

Entity Framework が速度を落としているだけなのか、表示されているメッセージがスレッド プールが作業項目のバックログをクリアしているだけなのか、それとも何か大きな問題が発生しているのかを判断する方法がわかりません。このような問題を解決するにはどうすればよいですか?

より良い解決策は、QDataメソッドで行うように、着信 JSON 文字列を byte[] としてキューに入れ、スレッド プールに別のメソッドをキューに入れさせて、キューをクリアすることです。その解決策は問題を変えるだけで、実際には解決しないと思います。

別の解決策は、そのキューをクリアする専用の新しいサービスを作成することでしょうか? 別のサービスを作成する際に発生する問題は、2 つのサービス間で通信するために WCF (または zmq) を使用する必要があり、明らかにオーバーヘッドが追加され、パフォーマンスが低下する可能性があることです。

私が購読している発行元は、購読者が追いつかない場合にメッセージを破棄し始めるように設定されているため、これらすべての重要なセクションは、ネットワークからデータを十分に速く取得することの一部であることがわかります。

4

0 に答える 0