开发者

How to ensure that a semaphore is not released until I release a subsequent semaphore?

开发者 https://www.devze.com 2023-03-16 17:05 出处:网络
My application fetches data from a live feed and at a time only one call can be made to the live feed. I call foreach for around 20 scenarios and then for each of these scenarios I\'ve to call the liv

My application fetches data from a live feed and at a time only one call can be made to the live feed. I call foreach for around 20 scenarios and then for each of these scenarios I've to call the live feed 15 times.

I'm kind of new to Threading and after trawling through internet and reading, I finally decided to use Semaphores. But I can't find a way to keep first the semaphore (_pool for the scenarios) in wait until live feed is called 15 times for that particular scenario.

And I'd appreciate if there is a more elegant solution to this problem (which I'm sure there is) Thanks in advance.

    private void button1_Click(object sender, EventArgs e)
    {
        _pool = new Semaphore(0, 1);
        foreach (string s in str)
        {
            Thread n = new Thread(new ParameterizedThreadStart(method1));
            n.Start(venue);            
        }
        _pool.Release(1);

开发者_StackOverflow社区    }


    static void method1(object venue)
    {
        _pool.WaitOne();

        for (int i = 1; i <= numThreads; i++)
        {
            string composite = i.ToString() + "," + venue;
            Thread n = new Thread(new ParameterizedThreadStart(method2));
            n.Start(composite);
        }
        _pool.Release(); //I need to ensure that this is called only after all threads
                         // spawned in the for loop corresponding to foreach thread are
                         // executed. But how?  
    }

    static void method2(object i)
    {
        _pool2.WaitOne();

        //Call to data engine and storing data in txt file

         Thread.Sleep(100);

         _pool2.Release();


    }


having either the primary thread (P) or some worker thread (W) that in turn spawns one or more additional threads (AT) only to have either P or W wait until all AT complete is not the best use of threads. in scenario P you may as well invoke method2() directly since P is blocked until AT completes anyway. the same can be said for situation W.

WaitAll() or waiting on an event is another way but just as bad perhaps because its forcing the caller to block. such a pattern does not scale well and wastes a thread when it could be doing something else.

an alternative is to use asynchronous notifications or thread marshalling to alert the main thread (or parent) when each thread exits. because your application is a GUI you can make use of .NET's Control.Invoke() or Control.BeginInvoke(). from your worker thread, simply call myForm.BeginInvoke(...) to alert a method in myForm that your thread has just exited and have all new task management handled there rather than in some other middle thread W.

there are some important differences between Invoke() and BeginInvoke(). Invoke() blocks the worker thread while the call is marshalled to the UI thread and wont return until the latter completes. so its probably not a good idea to use it in this case.

BeginInvoke() calls the method in the UI thread asynchronously via the Windows Message Pump. your worker thread is not blocked. this is the best choice.

0

精彩评论

暂无评论...
验证码 换一张
取 消