Semaphore和SemaphoreSlim使用最佳实践

时间:2016-03-30 07:59:23

标签: c# multithreading semaphore

我在这个类的顶部创建了一个信号量实例

public static SemaphoreSlim _zReportSemaphore = new SemaphoreSlim(1, 500);

在我的代码中,我需要检索并发送一些数据。

while (_isRunning)
{
    try
    {
        xBsonDocument = null;
        //I think its very clear in this line...
        MongoDBDAO.xGetInstance().GetZReportData(ref xBsonDocument);

        foreach (BsonDocument item in xBsonDocument)
        {
            try
            {
                ThreadObject xThreadObject = new ThreadObject();
                xThreadObject.m_strTerminalId = item.GetValue("_id")["TERMINAL_ID"].ToString();
                xThreadObject.m_strZNo = item.GetValue("_id")["Z_NO"].ToString();

                m_xBuildAndSendZReportThread = 
                    new Thread(new ParameterizedThreadStart(vBuildAndSendZReport));
                m_xBuildAndSendZReportThread.Start(xThreadObject);
            }
            catch (Exception xException)
            {
                xException.TraceError();
                continue;
            }

            Thread.Sleep(m_litleStepQTime); 
        }
    }
    catch (Exception xException)
    {
        Thread.Sleep(m_bigStepQTime);
        Trace.vInsertError(xException);
        continue;
    }

    Thread.Sleep(m_iSleepTime);
}

此主题目标是将文件发送到ftp

        private void vBuildAndSendZReport(object prm_objParameters)
        {
            _zReportSemaphore.Wait();
            RetriveDataFromMongoAndSend();
            _zReportSemaphore.Release();
        }

在这个结构中;如果我不使用信号量它工作得很好但有时线程计数超载CPU或内存使用量和机器一直在粉碎。

1-如何使用这种纤细的信号量控制数据使用(平衡,隔离线程等)?

2-我可以在生产中使用SemaphoreSlim进行此类工作吗?使用像这样的工作流程组织可能有什么优缺点? 是否可以改善效果?在我的特殊情况下

3-是否有另一种替代方案可以提供系统资源管理,并将结束技术异常管理

2 个答案:

答案 0 :(得分:2)

  

当信号量结束其所有线程时是否有任何事件

没有。它甚至不清楚这可能意味着什么。例如,如果由于线程调度问题,此时您在信号量中只有一个正在运行的线程,并且该线程在一个或多个其他线程尝试之前完成,释放信号量,那么您希望发生什么?获得信号量?

信号量无法检测到这种情况与每个线程不同。

如果您想知道某些异步操作集合何时完成,您需要特别等待。 .NET中有许多选项,包括:

  1. 在您已启动的所有主题对象上调用Thread.Join()
  2. 使用Task来运行异步任务而不是Thread,并使用Task.WhenAll()(或更不用说Task.WaitAll())等待它们完成。
  3. 使用CountdownEvent。为您开始的每项任务致电AddCount(),让每项任务在完成后调用Signal(),然后等待CountdownEvent

  4. 顺便说一下,您发布的代码在其他方面是可疑的:

    1. 为什么要指定SemaphoreSlim的最大数量,为什么这个最大值与初始计数不一样?您实际上是否希望比拨打Release()更频繁地致电Wait()
    2. 调用Thread.Sleep()的代码通常不正确。不清楚为什么要这样做,但可能有更好的方法来解决你试图用这些电话解决的任何问题。
    3. 没有好Minimal, Complete, and Verifiable example,我无法肯定地说那些事情是错的。但他们说得对的可能性很小。 :)

答案 1 :(得分:2)

这是“Semaphore 和 SemaphoreSlim 使用最佳实践”在 Google 上的第一次点击,所以我想添加 1 条评论:

至少,这段代码

    semaphore.Wait();
    DoSomeThing();
    semaphore.Release();

应该是最低的

    semaphore.Wait();
    try
    {
        DoSomeThing();
    }
    finally
    {
        semaphore.Release();
    }

否则,如果 DoSomeThing 中发生异常,您可能最终永远不会再次释放信号量...

在异步编程中,考虑使用

    await semaphore.WaitAsync();