C# 信号量LIM在释放前是否已处理?

C# 信号量LIM在释放前是否已处理?,c#,task,C#,Task,在对已接受答案的更新中提到 信号量可以在任务完成之前释放,并且在调用Release方法时会引发异常,因此在退出using块之前必须等待所有创建的任务完成 这怎么会发生 我将在此处粘贴代码: int maxConcurrency=10; var messages = new List<string>(); using(SemaphoreSlim concurrencySemaphore = new SemaphoreSlim(maxConcurrency)) { List<

在对已接受答案的更新中提到

信号量可以在任务完成之前释放,并且在调用Release方法时会引发异常,因此在退出using块之前必须等待所有创建的任务完成

这怎么会发生

我将在此处粘贴代码:

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());
}