Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我试图在循环中调用一个方法。它应该在10秒内只被调用20次。我使用的信号量如下代码所示_C#_Multithreading_Semaphore - Fatal编程技术网

C# 我试图在循环中调用一个方法。它应该在10秒内只被调用20次。我使用的信号量如下代码所示

C# 我试图在循环中调用一个方法。它应该在10秒内只被调用20次。我使用的信号量如下代码所示,c#,multithreading,semaphore,C#,Multithreading,Semaphore,通过使用下面的代码,首先,有些呼叫没有被拨打,比如说,在250个呼叫中,有238个呼叫被拨打,其余的没有。其次,我不确定这些呼叫是否以每10秒20个呼叫的速率拨打 public List<ShowData> GetAllShowAndTheirCast() { ShowResponse allShows = GetAllShows(); ShowCasts showCast = new ShowCasts(); showCas

通过使用下面的代码,首先,有些呼叫没有被拨打,比如说,在250个呼叫中,有238个呼叫被拨打,其余的没有。其次,我不确定这些呼叫是否以每10秒20个呼叫的速率拨打

public List<ShowData> GetAllShowAndTheirCast()
    {
        ShowResponse allShows = GetAllShows();

        ShowCasts showCast = new ShowCasts();
        showCast.showCastList = new List<ShowData>();


        using (Semaphore pool = new Semaphore(20, 20))
        {
            for (int i = 0; i < allShows.Shows.Length; i++)
            {
                pool.WaitOne();
                Thread t = new Thread(new ParameterizedThreadStart((taskId) =>
                {
                 showCast.showCastList.Add(MapResponse(allShows.Shows[i]));
                }));
                pool.Release();
                t.Start(i);
            }
        }
        //for (int i = 0; i < allShows.Shows.Length; i++)
        //{
        //    showCast.showCastList.Add(MapResponse(allShows.Shows[i]));
        //}

        return showCast.showCastList;
    }

 public ShowData MapResponse(Show s)
    {
        CastResponse castres = new CastResponse();
        castres.CastlistResponse = (GetShowCast(s.id)).CastlistResponse;
        ShowData sd = new ShowData();
        sd.id = s.id;
        sd.name = s.name;
        if (castres.CastlistResponse != null && castres.CastlistResponse.Any())
        {

            sd.cast = new List<CastData>();
            foreach (var item in castres.CastlistResponse)
            {
                CastData cd = new CastData();
                cd.birthday = item.person.birthday;
                cd.id = item.person.id;
                cd.name = item.person.name;
                sd.cast.Add(cd);
            }

        }
        return sd;
    }
public ShowResponse GetAllShows()
    {
        ShowResponse response = new ShowResponse();
        string showUrl = ClientAPIUtils.apiUrl + "shows";
        response.Shows = JsonConvert.DeserializeObject<Show[]>(ClientAPIUtils.GetDataFromUrl(showUrl));
        return response;
    }

    public CastResponse GetShowCast(int showid)
    {
        CastResponse res = new CastResponse();
        string castUrl = ClientAPIUtils.apiUrl + "shows/" + showid + "/cast";
        res.CastlistResponse = JsonConvert.DeserializeObject<List<Cast>>(ClientAPIUtils.GetDataFromUrl(castUrl));
        return res;
    }
public List getallshowntheircast()
{
ShowResponse allShows=GetAllShows();
ShowCasts showCast=新的ShowCasts();
showCast.showCastList=新列表();
正在使用(信号量池=新信号量(20,20))
{
for(int i=0;i
{
showCast.showCastList.Add(MapResponse(allShows.Shows[i]);
}));
pool.Release();
t、 启动(i);
}
}
//for(int i=0;i

所有的电话都应该打,但我不确定他们在哪里被中止,甚至请让我知道如何检查通话率

我假设您的目标是一次处理所有关于节目的数据,但不超过20个。 对于这种任务,您可能应该使用
ThreadPool
,并使用
SetMaxThreads
限制并发线程的最大数量

您必须确保用于存储结果的集合是线程安全的

showCast.showCastList = new List<ShowData>();
我没有测试这个解决方案;可能会出现其他问题

这个程序的另一个问题是它不等待所有线程完成。一旦所有线程启动;节目将结束。有可能(在您的情况下,我确信)不是所有线程都完成了它的操作;这就是为什么程序结束时会产生约240个数据包

thread.Join();
但是如果在
Start()
之后立即调用,它将停止主线程,直到它完成为止,因此为了保持程序的并发性,您需要创建一个线程列表,并在程序结束时将它们连接起来。这不是最好的解决办法。如何等待程序可以添加到
ThreadPool

最后请注意,您不能像那样访问循环计数器。稍后评估循环计数器的最终值,并运行测试I;代码有两次处理奇数记录和跳过偶数记录的倾向。发生这种情况是因为循环在执行前一个线程之前增加计数器,并导致访问数组边界之外的元素

可能的解决方案是创建将创建线程的方法。在下一个循环通过之前,将其置于单独的方法中,将对
allShows.Shows[i]
进行评估,以
show

public void CreateAndStartThread(Show show, Semaphore pool, ShowCasts showCast)
{
        pool.WaitOne();
        Thread t = new Thread(new ParameterizedThreadStart((s) => {
            showCast.showCastList.Add(MapResponse((Show)s));
            pool.Release();
        }));
    t.Start(show);
}
并发编程是很棘手的,我强烈建议大家做一些关于常见陷阱的练习。关于C#编程的书肯定有一两章是关于这个主题的。有很多关于这个主题的在线课程和教程可供学习

编辑: 工作解决方案。可能还有一些问题

    public ShowCasts GetAllShowAndTheirCast()
        {
            ShowResponse allShows = GetAllShows();

            ConcurrentBag<ShowData> result = new ConcurrentBag<ShowData>();
            using (var countdownEvent = new CountdownEvent(allShows.Shows.Length))
            {
                using (Semaphore pool = new Semaphore(20, 20))
                {
                    for (int i = 0; i < allShows.Shows.Length; i++)
                    {
                        CreateAndStartThread(allShows.Shows[i], pool, result, countdownEvent);
                    }

                    countdownEvent.Wait();
                }     
            }
            return new ShowCasts() { showCastList = result.ToList() };
        }

    public void CreateAndStartThread(Show show, Semaphore pool, ConcurrentBag<ShowData> result, CountdownEvent countdownEvent)
        {
            pool.WaitOne();
            Thread t = new Thread(new ParameterizedThreadStart((s) =>
            {
                result.Add(MapResponse((Show)s));
                pool.Release();
                countdownEvent.Signal();
            }));

            t.Start(show);
        }
public ShowCasts getallshowtheircast()
{
ShowResponse allShows=GetAllShows();
ConcurrentBag结果=新ConcurrentBag();
使用(var countdownEvent=new countdownEvent(allShows.Shows.Length))
{
正在使用(信号量池=新信号量(20,20))
{
for(int i=0;i
{
结果.添加(MapResponse((Show)s));
pool.Release();
倒计时事件。信号();
}));
t、 开始(表演);
}

Waitone的使用方式没有多大意义。WaitOne用于两个不同的线程。我想你应该用锁来代替。
    public ShowCasts GetAllShowAndTheirCast()
        {
            ShowResponse allShows = GetAllShows();

            ConcurrentBag<ShowData> result = new ConcurrentBag<ShowData>();
            using (var countdownEvent = new CountdownEvent(allShows.Shows.Length))
            {
                using (Semaphore pool = new Semaphore(20, 20))
                {
                    for (int i = 0; i < allShows.Shows.Length; i++)
                    {
                        CreateAndStartThread(allShows.Shows[i], pool, result, countdownEvent);
                    }

                    countdownEvent.Wait();
                }     
            }
            return new ShowCasts() { showCastList = result.ToList() };
        }

    public void CreateAndStartThread(Show show, Semaphore pool, ConcurrentBag<ShowData> result, CountdownEvent countdownEvent)
        {
            pool.WaitOne();
            Thread t = new Thread(new ParameterizedThreadStart((s) =>
            {
                result.Add(MapResponse((Show)s));
                pool.Release();
                countdownEvent.Signal();
            }));

            t.Start(show);
        }