【问题标题】:while(true) or a tcp listen : what is more efficient?while(true) 或 tcp 侦听:什么更有效?
【发布时间】:2010-01-08 14:12:05
【问题描述】:

我希望我的程序持续等待触发器以执行下一个任务。

  1. 一种选择是池化:使用无限循环,例如而(真)
  2. 或者,TCP 是否侦听超时相对较高的端口。

我想知道这两种技术中的哪一种会更有效地保持我的应用程序存活?

我觉得执行 while(true) 会是一个杀手,而 tcp listen 可能是一个健康选项,因为 tcp listen 会使用硬件中断?

此外,在 .net winform 应用程序中,我们有 Application.Run() 方法可以使应用程序保持活动状态。如果有人知道这种方法在内部做什么,请分享。

PS:这里我已经考虑过 msmq 选项(相当于 tcp listen),但我不想依赖 msmq。

【问题讨论】:

  • 关于“也”部分:请单独提出。
  • 您还在等什么?如果您正在等待 TCP 连接,那么最好听,否则是可等待对象之一,例如AutoResetEvent,会更好。对于 WaitHandles,请参阅 yoda.arachsys.com/csharp/threads/waithandles.shtml

标签: c#


【解决方案1】:

除非您实际上是在等待 TCP/IP 端口上发生的事情,否则您不应该(ab)使用Listen

一种有效的方法是AutoResetEvent,当您想要触发任务处理时发出信号。这将使您的线程休眠,直到它需要做某事,而无需任何轮询。

class TaskProcessor
{
    AutoResetEvent newTaskHandle = new AutoResetEvent(false);
    Queue<Task> taskQueue = new Queue<Task>();
    object syncRoot = new object();

    public void ProcessTasks()
    {
        while (true)
        {
            newTaskHandle.WaitOne();

            Task task = null;

            lock (syncRoot)
            {
                if (taskQueue.Count > 0)
                {
                    task = taskQueue.Dequeue();
                }
            }

            // Do task
        }
    }

    public void AddTask(Task task)
    {
        lock (syncRoot)
        {
            taskQueue.Enqueue(task);
            newTaskHandle.Set();
        }
    }
}

这可能会引发如何中止处理任务的问题。您可以使用多个WaitHandler(AutoResetEvent 从中继承)并等待其中任何一个发生:

WaitHandle[] handles = new WaitHandle[] { newTaskHandle, stopHandle };

int signalledHandle = WaitHandle.WaitAny(handles);

或者,您可以引入一个简单的布尔值并重用相同的事件。如果您想确保在停止之前处理所有任务,这实际上可能更可取。

【讨论】:

  • 我认为他们需要为这样的答案创建一个名为“Vote Squatter”“Answer Placeholder”的新徽章。 :)
  • John:确实.. 有时看到最佳答案是后来添加的,但没有获得 任何 票,这有时有点令人难过,因为人们只阅读前几个。这就是为什么我养成了快速提供简短答案的习惯,然后我对此进行了扩展。
【解决方案2】:

这个触发器的来源是什么?相同的应用程序、相同的 PC、网络?

相同的应用程序:使用AutoResetEvent 同一台 PC 上的另一个应用程序:使用 MutexSemaphore

是的,当触发源是另一台机器时,TCP 侦听会是更好的选择。

如果您的 WinForms 应用程序在您关闭最后一个窗口时没有结束,很可能您还有一些线程正在运行

【讨论】:

  • 关于使用命名互斥体进行进程间同步的要点。真的有很多可能性。一些额外的输入将避免必须全部解释:)
【解决方案3】:

我会考虑将您的代码部分放入一个单独的线程中,让线程等待释放您的 UI,让您的 UI 监听事件:

var tcpConnectionMade = new AutoResetEvent(false);
System.Threading.ThreadPool.QueueUserWorkItem(delegate 
{
    // listen for TCP connection
    ...
    // once connected
    tcpConnectionMade.Set();
});

// wait for TCP connection
WaitHandle.WaitOne(tcpConnectionMade);

// do something when connected...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-02
    • 1970-01-01
    • 2011-01-16
    • 2019-10-07
    • 1970-01-01
    • 2011-04-26
    • 2023-03-14
    相关资源
    最近更新 更多