Semaphore 和 SemaphoreSlim 使用最佳实践
Semaphore and SemaphoreSlim usage Best Practices
我在此基础上创建了一个信号量实例 class
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- 我如何使用这个 slim 信号量来控制数据使用(平衡、隔离线程等)?
2- 我可以将 SemaphoreSlim 用于生产中的此类工作吗?使用这样的工作流组织有哪些优点和缺点?
它会提高性能吗?在我的特殊情况下
3- 是否有另一种替代方案可以提供系统资源管理并结束技术异常管理
更新:
我在很久以前做的工作中问过这个问题。解决问题后才发现我没有return.
在上面的示例中,报告发送作业发生在文件共享环境中。其他解决方案也是可能的,例如使用 CDN。
问题是:如果线程不能让我知道它在做什么,如果它不告诉我它是否已经取得成功,我为什么要使用线程?我为什么要用 SemaphoreSlim 为例!?
是的,当然可以用异步编程来完成。但我不想将这个库包含在相关环境中。它必须是。我敢肯定很多代码都需要这种情况。
我的解决方案是这样的:我消除了抛出异常的代码中出现异常的可能性。所以我将冲突与应用程序外部的线程同步。我做了一个线程池之类的东西。它作为消费者完美地工作。我通过设置自定义计时机制来做到这一点。
不管怎样,我还是同意的。应该设置一个线程来携带有关它正在执行的工作的信息。我不是在谈论在两者之间编写 Mutex 对象。线程本身可以承载这些信息。
顺便给回答的人加分。因为他们根据问题给出了正确的评论。
Is there any event when semaphore ends its all threads
没有。甚至不清楚这可能意味着什么。例如,如果由于线程调度问题,此时信号量中只有一个 运行ning 线程,并且该线程在一个或多个其他线程之前完成并释放信号量,您希望发生什么线程甚至可以尝试获取信号量?
信号量无法检测到这种情况,因为每个线程都在完成。
如果您想知道某些异步操作集合何时完成,您需要专门等待。您在 .NET 中有多种选择,包括:
- 对您启动的所有线程对象调用
Thread.Join()
。
- 使用
Task
来 运行 您的异步任务而不是 Thread
,并使用 Task.WhenAll()
(或者更不理想,Task.WaitAll()
)来等待它们完成。
- 使用
CountdownEvent
。为您开始的每个任务调用 AddCount()
,让每个任务在完成时调用 Signal()
,然后等待 CountdownEvent
.
顺便说一下,您发布的代码在其他方面存在问题:
- 为什么要为
SemaphoreSlim
指定最大计数,为什么这个最大值与初始计数不同?你真的希望调用 Release()
比你调用 Wait()
更频繁吗?
- 调用
Thread.Sleep()
的代码通常不正确。目前尚不清楚您这样做的原因,但很可能有更好的方法来解决您试图通过这些调用解决的任何问题。
没有好的Minimal, Complete, and Verifiable example,我不能肯定地说那些东西是错的。但他们是对的可能性很小。 :)
这是“Semaphore 和 SemaphoreSlim 使用最佳实践”在 Google 上的第一次点击,所以我想补充 1 条评论:
至少,这段代码
semaphore.Wait();
DoSomeThing();
semaphore.Release();
应该是最小值
semaphore.Wait();
try
{
DoSomeThing();
}
finally
{
semaphore.Release();
}
否则,如果在 DoSomeThing 中发生异常,您可能最终再也不会释放信号量...
并且在异步编程中,考虑使用
await semaphore.WaitAsync();
我在此基础上创建了一个信号量实例 class
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- 我如何使用这个 slim 信号量来控制数据使用(平衡、隔离线程等)?
2- 我可以将 SemaphoreSlim 用于生产中的此类工作吗?使用这样的工作流组织有哪些优点和缺点? 它会提高性能吗?在我的特殊情况下
3- 是否有另一种替代方案可以提供系统资源管理并结束技术异常管理
更新: 我在很久以前做的工作中问过这个问题。解决问题后才发现我没有return.
在上面的示例中,报告发送作业发生在文件共享环境中。其他解决方案也是可能的,例如使用 CDN。
问题是:如果线程不能让我知道它在做什么,如果它不告诉我它是否已经取得成功,我为什么要使用线程?我为什么要用 SemaphoreSlim 为例!?
是的,当然可以用异步编程来完成。但我不想将这个库包含在相关环境中。它必须是。我敢肯定很多代码都需要这种情况。
我的解决方案是这样的:我消除了抛出异常的代码中出现异常的可能性。所以我将冲突与应用程序外部的线程同步。我做了一个线程池之类的东西。它作为消费者完美地工作。我通过设置自定义计时机制来做到这一点。
不管怎样,我还是同意的。应该设置一个线程来携带有关它正在执行的工作的信息。我不是在谈论在两者之间编写 Mutex 对象。线程本身可以承载这些信息。
顺便给回答的人加分。因为他们根据问题给出了正确的评论。
Is there any event when semaphore ends its all threads
没有。甚至不清楚这可能意味着什么。例如,如果由于线程调度问题,此时信号量中只有一个 运行ning 线程,并且该线程在一个或多个其他线程之前完成并释放信号量,您希望发生什么线程甚至可以尝试获取信号量?
信号量无法检测到这种情况,因为每个线程都在完成。
如果您想知道某些异步操作集合何时完成,您需要专门等待。您在 .NET 中有多种选择,包括:
- 对您启动的所有线程对象调用
Thread.Join()
。 - 使用
Task
来 运行 您的异步任务而不是Thread
,并使用Task.WhenAll()
(或者更不理想,Task.WaitAll()
)来等待它们完成。 - 使用
CountdownEvent
。为您开始的每个任务调用AddCount()
,让每个任务在完成时调用Signal()
,然后等待CountdownEvent
.
顺便说一下,您发布的代码在其他方面存在问题:
- 为什么要为
SemaphoreSlim
指定最大计数,为什么这个最大值与初始计数不同?你真的希望调用Release()
比你调用Wait()
更频繁吗? - 调用
Thread.Sleep()
的代码通常不正确。目前尚不清楚您这样做的原因,但很可能有更好的方法来解决您试图通过这些调用解决的任何问题。
没有好的Minimal, Complete, and Verifiable example,我不能肯定地说那些东西是错的。但他们是对的可能性很小。 :)
这是“Semaphore 和 SemaphoreSlim 使用最佳实践”在 Google 上的第一次点击,所以我想补充 1 条评论:
至少,这段代码
semaphore.Wait();
DoSomeThing();
semaphore.Release();
应该是最小值
semaphore.Wait();
try
{
DoSomeThing();
}
finally
{
semaphore.Release();
}
否则,如果在 DoSomeThing 中发生异常,您可能最终再也不会释放信号量...
并且在异步编程中,考虑使用
await semaphore.WaitAsync();