0

キューに無限ループを使用するとtryDequeue、CPU が過剰に使用されます。

キューが空でない場合、この操作をユーザー インターフェイス通知として実行することは可能ですか? そして、それをイベントまたは関数で実行しますか?

ZeroMQ ライブラリを使用する私の実装では、パブリッシュを主に担当するスレッドで、無限ループは避けられないという結論に達しました。

using (var context = new Context(1)){
                    using (Socket client = context.Socket(SocketType.PUB)){
while (!StopAllThread){
   SQLQueue.TryDequeue(out message);
   if (message != null){
   ...
   }
}
}
4

3 に答える 3

1

BlockingCollection、このような場合に役立ちます。

例えば:

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

namespace Demo
{
    public class Program
    {
        private readonly BlockingCollection<string> _queue = new BlockingCollection<string>();

        private void run()
        {
            Task.Run(() => producer());
            consumer();

            Console.WriteLine("Press <return> to exit.");
        }

        private void consumer()
        {
            Console.WriteLine("consumer() starting.");

            foreach (var item in _queue.GetConsumingEnumerable())
            {
                Console.WriteLine("consumer() processing item " + item);
            }

            Console.WriteLine("consumer() stopping.");
        }

        private void producer()
        {
            Console.WriteLine("producer() starting.");

            for (int i = 0; i < 20; ++i)
            {
                _queue.Add(i.ToString());
                Thread.Sleep(200);
            }

            Console.WriteLine("producer() finishing.");

            _queue.CompleteAdding(); // Calling this makes the consumer exit its foreach loop.
        }

        private static void Main(string[] args)
        {
            new Program().run();
        }

    }
}

新しいアイテムがキューに表示されるのを待っているときに自動的にブロックする列挙型を取得するために呼び出す方法に注意してくださいGetConsumingEnumerable()。ただし、キューがCompleteAdding()プロデューサー スレッドの呼び出しによって完了としてマークされるとすぐに終了します。

于 2013-08-26T08:49:57.330 に答える
0

をカスタマイズしQueueてイベントを追加し、イベントを処理してアイテムのエンキューとデキューについて通知できます。

public class CustomQueue<T> : Queue<T>
{
    public event EventHandler ItemDequeued;
    public event EventHandler ItemEnqueued;
    public new void Enqueue(T item)
    {
        base.Enqueue(item);
        if (ItemEnqueued != null) ItemEnqueued(this, EventArgs.Empty);
    }
    public new T Dequeue()
    {
        T a = base.Dequeue();
        if (ItemDequeued != null) ItemDequeued(this, EventArgs.Empty);
        return a;
    }
}
//Then you can handle the event ItemDequeued to know if its Count = 0
yourQueue.ItemDequeued += (s, e) =>{
   if (yourQueue.Count == 0) MessageBox.Show("EMPTY queue!");
};
yourQueue.ItemEnqueued += (s,e) => {
   //you can try running code asynchronously here;
};
于 2013-08-26T08:32:51.987 に答える