C# 信号量LIM在释放前是否已处理?
在对已接受答案的更新中提到 信号量可以在任务完成之前释放,并且在调用Release方法时会引发异常,因此在退出using块之前必须等待所有创建的任务完成 这怎么会发生 我将在此处粘贴代码:C# 信号量LIM在释放前是否已处理?,c#,task,C#,Task,在对已接受答案的更新中提到 信号量可以在任务完成之前释放,并且在调用Release方法时会引发异常,因此在退出using块之前必须等待所有创建的任务完成 这怎么会发生 我将在此处粘贴代码: int maxConcurrency=10; var messages = new List<string>(); using(SemaphoreSlim concurrencySemaphore = new SemaphoreSlim(maxConcurrency)) { List<
int maxConcurrency=10;
var messages = new List<string>();
using(SemaphoreSlim concurrencySemaphore = new SemaphoreSlim(maxConcurrency))
{
List<Task> tasks = new List<Task>();
foreach(var msg in messages)
{
concurrencySemaphore.Wait();
var t = Task.Factory.StartNew(() =>
{
try
{
Process(msg);
}
finally
{
concurrencySemaphore.Release();
}
});
tasks.Add(t);
}
Task.WaitAll(tasks.ToArray());
}
所以1。为什么需要任务列表
二,。在我的例子中,没有foreach,而是一个套接字随机接受请求&调用Task.Factory.StartNew。我不能等待所有线程完成。这个信号量方法还能使用吗
为什么需要任务列表
调用Task.WaitAll以等待所有任务完成,然后再释放信号量LIM。如果不执行此操作,则可能在所有任务完成之前释放信号量LIM,然后在其余任何任务调用concurrencySemaphore.Release时,您将获得ObjectDisposedException
您正在创建消息。计算任务数,信号量LIM接受maxConcurrency 10初始请求数。因此,如果例如messages.Count等于5,则所有五个任务都将在处理信号量LIM之前或多或少地启动并添加到任务中,除非调用Task.WaitAll
考虑以下示例代码,其中我注释掉了对Task.WaitAll的调用,并将对Process的调用替换为对Thread.Sleep的调用:
此代码将为每个任务抛出ObjectDisposedException
我不能等待所有线程完成。这个信号量方法还能使用吗
如果您的任务访问信号量LIM的任何成员,则在确定所有任务都已完成之前,不应处置它。如果您不能或不想等待任务完成,您可能应该将信号量lim定义为类的私有字段,并实现IDisposable接口。信号量可能在任务完成之前被释放-这在当前版本的代码中是不可能的。评论是针对先前版本的答案@DmitryPavlip-是的,问题是为什么需要更新,特别是在发布前如何处理信号量。这对问题没有帮助,可能对您的应用程序没有影响,但从技术上讲;不应该是马普霍尔,等等;是否放置在StartNew=>中,就在尝试之前?@MichaelPuckettII:您正在创建消息。计算任务数,信号量LIM接受maxConcurrency初始请求数。如果省略Task.WaitAll,则会出现两个问题。是的,释放调用可能会爆炸,因为主线程启动并释放信号量。但更糟,更糟。你不会注意到的。任务中的代码引发的任何异常都不会被注意到。在没有诊断的情况下随机失效的代码是不可能可靠的。
int maxConcurrency = 10;
var messages = new List<string>() { "1", "2", "3" };
using (SemaphoreSlim concurrencySemaphore = new SemaphoreSlim(maxConcurrency))
{
//List<Task> tasks = new List<Task>();
foreach (var msg in messages)
{
concurrencySemaphore.Wait();
var t = Task.Factory.StartNew(() =>
{
try
{
Thread.Sleep(5000);
}
finally
{
concurrencySemaphore.Release();
}
});
//tasks.Add(t);
}
//Task.WaitAll(tasks.ToArray());
}