【问题标题】:AutoResetEvent inside of WCF process sometimes not waking up threadWCF 进程内部的 AutoResetEvent 有时不会唤醒线程
【发布时间】:2017-02-20 23:29:04
【问题描述】:

我正在开发一个运行一些后台线程以将数据写入数据库的 WCF 服务。后台线程使用标准的生产者和消费者模式实现:

private readonly Queue<DatabaseChange> ChangeQueue = new Queue<DatabaseChange>();

public Worker(int id)
{
    var workerThread = new Thread(SynchronizationWorker)
    {
        IsBackground = true,
        Name = "deltaQ-" + id,
        Priority = ThreadPriority.Highest
    };
    workerThread.Start();
}

private void SynchronizationWorker()
{
    while (true)
    {                  
            s_Logger.Info("waiting for changes...");
            _changeAvailableEvent.WaitOne();

            s_Logger.Info("changes available, start persisting...");
            ...
            // actual work. not important because we never come here (as we can observe in the log file)
    }
}

public void Enqueue(DatabaseChange change)
{
    lock (ChangeQueue)
    {
        ChangeQueue.Enqueue(change);
    }
    _changeAvailableEvent.Set();
}

服务以单实例模式运行。

现在我们观察到:

工作线程启动,一段时间内一切正常。

然后在某个时候,即使将数据添加到队列和事件集中,工作线程也不知何故不再唤醒。

工作线程也具有最高优先级,因此即使服务器非常繁忙,它们也应该获得时间片。

我现在不知道该怎么办,似乎 IIS 主机进程在某个时候决定不再调度工作线程。

【问题讨论】:

    标签: c# multithreading wcf synchronization


    【解决方案1】:

    这里的问题是 IIS。由于您无法控制的原因,IIS 工作进程可以随时关闭。此外,工作进程在回收时可能会重叠。

    在您的情况下,Windows 服务将是更好的选择。

    查看此帖子了解更多详情:WCF hosted in IIS vs in Windows Service

    【讨论】:

    • 主机进程没有关闭。该进程仍然存在,日志条目是从其他请求创建的。只有数据库的工作线程不再运行
    • 没错,您不能放弃 WCF 线程。如果您启动一个请求,该请求会启动一些后台工作人员,然后返回,那么您的工作线程就会丢失。在返回 WCF 响应之前,您必须等待完成所有后台线程。如果你使用 Windows 服务,你可以在 WCF 中创建一个异步方法,它允许你启动后台线程并稍后返回......你不能在 IIS 中这样做。
    • 这不会发生在实例上下文模式单一的情况下:
    • [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)] 我们还有其他工作线程,它们正在运行。出于某种原因,只有这些特定线程永远不会被安排运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    • 1970-01-01
    相关资源
    最近更新 更多