多个任务调度导致死锁

时间:2014-08-29 19:16:44

标签: c# multithreading

该应用程序用于电话服务。所有呼叫都被放入队列中。由于端口限制,每次应用程序最多只能调用4次。

在下面的代码中,我将最大信号量设置为4当然。

然而,在这个小型模拟程序中,它陷入了僵局。任务都没有完成。

class Program
{
    static readonly Queue<string> phoneNumbers = new Queue<string>();
    static Semaphore semaphore;
    static void Main(string[] args)
    {
        string[] dialCollection = new string[9];
        dialCollection[0] = "test 00000000000";
        dialCollection[1] = "test 11111111111";
        dialCollection[2] = "test 22222222222";
        dialCollection[3] = "test 33333333333";
        dialCollection[4] = "test 44444444444"; 
        dialCollection[5] = "test 55555555555";
        dialCollection[6] = "test 66666666666";
        dialCollection[7] = "test 77777777777";
        dialCollection[8] = "test 88888888888";
        foreach (var item in dialCollection)
        {
            phoneNumbers.Enqueue(item);
        }
        semaphore = new Semaphore(0, 4);
        Console.WriteLine("Begin");
        List<Task> tasks = new List<Task>();
        do
        {
            string phoneNumber = phoneNumbers.Dequeue();
            try
            {
                tasks.Add(Task.Factory.StartNew(() => { MakeCall(phoneNumber); }));
            }
            catch (Exception)
            {
                //put the number back in the queue if the MakeCall method throws an exception...
                phoneNumbers.Enqueue(phoneNumber);
            }
        }
        while (phoneNumbers.Count > 0);
        Task.WaitAll(tasks.ToArray());
        Console.WriteLine("End");  //code not reach this break point.
        Console.Read();
    }

    private static void MakeCall(string phoneNumber)
    {
        semaphore.WaitOne();
        Console.WriteLine(phoneNumber);
        semaphore.Release();
    }
}

2 个答案:

答案 0 :(得分:3)

您对信号量的初始计数设置为0,因此没有可用的信号。你有两个选择,用四个可用的构建它:

semaphore = new Semaphore(4, 4);

或者在开始WaitAll

之前释放4
semaphore.Release(4);

答案 1 :(得分:1)

您将信号量的初始值设置为0,这意味着在您的程序开始时,零项可以从WaitOne返回,直到调用Release

您希望将信号量初始化为4,而不是0。