【问题标题】:Task.Factory.StartNew not executing the task when deployedTask.Factory.StartNew 部署时不执行任务
【发布时间】:2012-08-17 17:09:44
【问题描述】:

我有一些代码在我自己的计算机 Windows 7 上安装/运行时按预期工作,但当我在其他服务器(2003 和 2008)上运行时却没有。该代码来自我在 Windows 服务中使用的 .NET4 WCF 服务库。在这里,很简单。

public void monitorQueueAndDoStuff() {
  MonitorRetryQueue();
  MonitorMainQueue();                
}

private void MonitorMainQueue() {
  Log.Info("MonitorMainQueue called");
  Task.Factory.StartNew(() =>
  {
    Log.Info("new thread monitoring queue");
    // ...NMS stuff

        while (!stopped) {
          ITextMessage mess = null;
            mess = blockingMessageCollection.Take();
            sendToQueue(mess);
        }
      }
    }
  });
}


private void MonitorRetryQueue() {
  Task.Factory.StartNew(() =>
  {
    //...NMS stuff
        consumer.Listener += new MessageListener(OnRetryErrorMessage);
        Log.Info("new thread monitoring second queue");

        //need to be constantly up for the consumer to hang around
        while (!stopped) {
          Thread.Sleep(1000);
        }
      }
    }
      });
}

线程应该进入循环来做一些工作。 BlockingCollection 上的主要块。 现在,它创建了两个任务,但它只进入第二个,它从不在日志中打印“新线程监控队列”。我不明白为什么不。我尝试了远程调试,但由于它从不进入代码,我看不到任何有价值的东西。

我没有发现任何会改变已部署服务器上代码行为的东西。这里有人可能有线索吗? Visual Studio 项目中的任何设置?

【问题讨论】:

    标签: c# visual-studio-2010 .net-4.0 task-parallel-library


    【解决方案1】:

    有时这种行为表明ThreadPool 过载。

    鉴于这些是长时间运行/阻塞的任务,它们不应被安排在 ThreadPool 中运行,Task.Factory.StartNew 将使用默认的 TaskScheduler 发送它们。

    IMO,Task.Factory.StartNew 可能不适合这种情况,您最好启动自己的线程来运行这些循环。

    ThreadStart action=()=>{
        //do your thing
    };
    Thread thread=new Thread(action){IsBackground=true};
    thread.Start();
    

    【讨论】:

    • 我不得不同意,不一定是因为 ThreadPool 超载,但更多的是 Tasks 和线程池供那些不会“永远”运行的东西使用(任意数量的time) 像这样,而是需要一些有限的时间来完成一个动作。当您有一些想要“永远”运行的处理循环(直到它停止)时,这非常适合专用的后台线程(很像某些应用程序/框架将有一个专门的循环来泵送消息)
    • 谢谢,我原以为这可能会有所帮助,但恐怕它与ThreadStart 的行为相同。很高兴知道Task.Factory.StartNew 不适合。
    • 嗯,我找到了,和这些方法无关。这是一个它需要的 dll,我没有设置为复制本地。在我尝试命令行版本之前,我没有看到任何关于它的消息。我认为你的答案是正确的。
    • 同样的事情发生在我身上,我已将任务更改为线程,它就像一个魅力:)
    • 如果线程池过载,如何手动或编程检查?
    【解决方案2】:

    日志中是否会打印任何日志消息?你看到"MonitorMainQueue called" 被打印了吗?你怎么知道第二个任务已经启动但不是第一个?创建/写入日志文件可能是权限问题吗?

    编辑:此外,为了回应@spender 关于长时间运行任务的说法,使用该选项启动任务时会出现过载。

    Task.Factory.StartNew(MonitorMainQueue, TaskCreationOptions.LongRunning);

    【讨论】:

    • 这个答案的大部分应该是对原始问题的评论。
    • 我同意,但我没有足够的声望点来发表评论。 :)
    • 是的,"MonitorMainQueue called" 打印在日志中,但是从那个线程中没有更多内容,只有另一个(我已经从我的示例中删除了第二个线程中的日志语句,我现在把它放回去了)。两者都写入同一个日志,所以这无关紧要。在我的系统上,日志包含所有三个语句。我试过TaskCreationOptions.LongRunning,没有任何区别。
    【解决方案3】:

    我在部署到生产环境时遇到了同样的问题。

    问题是由于应用程序池使用的身份造成的。

    默认情况下,它使用的是权限受限的 applicationPoolIdentity。

    我们改为“网络服务”,它工作了。

    注意:我并不是说使用 NetWorkService 是最好的解决方案,但这显然是一个安全权利问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多