2

I am executing some .py scripts async. One Script takes about 30 seconds to be executed. It could happen that two or even more Scripts are being selected in a timespan of two or three seconds. The Goal is to have a Scheduler which collects all the tasks and executes them one after the other. A FIFO functionality should be included. I 've tried the following Code just to try the functionality of the queuedTaskScheduler, but even that doesn't work.

QueuedTaskScheduler queueScheduler;
private TaskScheduler ts_priority1;
int pos = 0;
        public Form1()
    {
        InitializeComponent();
        queueScheduler = new QueuedTaskScheduler(targetScheduler: TaskScheduler.Default, maxConcurrencyLevel: 1);
        ts_priority1 = queueScheduler.ActivateNewQueue(1);
    }
        private void button3_Click(object sender, EventArgs e)
    {
        QueueValue(pos, ts_priority1);
        pos++;
    }

    private void button4_Click(object sender, EventArgs e)
    {
        changeString(pos);
        pos++;
    }
    private void changeString (int position)
    {
        var bea = "This is Thread " + position + " starting";
        MethodInvoker Labelupdate = delegate
        {
            label2.Text = bea;
        };
        Invoke(Labelupdate);

        Thread.Sleep(3000);
        bea = "Thread " + position + " is ending";

        MethodInvoker Labelupdate1 = delegate
        {
            label2.Text = bea;
        };
        Invoke(Labelupdate1);
        Thread.Sleep(1000);
    }
    private void updateLabel (string Lab)
    {
        MethodInvoker Labelupdate = delegate
        {
            label2.Text = Lab;
        };
        Invoke(Labelupdate);
    }
    private Task QueueTask(Func<Task> f, TaskScheduler ts)
    {
        return Task.Factory.StartNew(f, CancellationToken.None, TaskCreationOptions.HideScheduler | TaskCreationOptions.DenyChildAttach, ts);
    }

    private Task QueueValue(int position, TaskScheduler ts)
    {
        return QueueTask(async () =>
        {
            label2.Text = "This is Thread " + position + " starting";
            Thread.Sleep(3000);
            label2.Text = "Thread " + position + " is ending";
            Thread.Sleep(1000);
        }, ts);
    }
DL Narasimhan
  • 731
  • 9
  • 25
a_hamm99
  • 171
  • 1
  • 12

1 Answers1

2

I solved it. There is only need of a Semaphore. It is the same way as in this Thread Here is the Code:

private static SemaphoreSlim semaphore = new SemaphoreSlim(1);
 private Task QueueValue(int position, TaskScheduler ts)
    {
        return QueueTask(async () =>
        {
            await semaphore.WaitAsync();
            try
            {
                var at = "This is Thread " + position + " starting";
                updateLabel(at);
                await Task.Delay(3000);
                at = "Thread " + position + " is ending";
                updateLabel(at);
                await Task.Delay(1000);
            }
            finally
            {

                semaphore.Release();
            }

        }, ts);
    }

Many thanks!

Community
  • 1
  • 1
a_hamm99
  • 171
  • 1
  • 12
  • Mixing semaphores and tasks is a smell. If you want to execute a single "task" at a time, you can use an ActionBlock. In fact, you can create an entire dataflow pipeline with different degrees of parallelism, load balancing etc using the TPL Dataflow library – Panagiotis Kanavos Feb 23 '16 at 16:35
  • 3
    @PanagiotisKanavos There's nothing wrong with using a `Semaphore` here at all. It's *specifically* designed for this exact type of use case. TPL Dataflow if fine if you want more advanced features, but if you don't need it, then this is fine. – Servy Feb 23 '16 at 17:04
  • @Servy there is a question open in [tpl-dataflow] where SemaphoreSlim actually causes a block to choke. SemaphoreSlim isn't a native construct and uses several tricks under the hood. As for simple/advanced, with ActionBlock, you just need `var block=new ActionBlock(msg=>Process(msg));` and you can start queueing work. – Panagiotis Kanavos Feb 23 '16 at 17:10
  • 1
    @PanagiotisKanavos Then you're claiming that there are problems with using *both together*, rather than using either one independently to solve a problem. Big difference. And you're suggesting installing an entire 3rd party tool into the program just to add that one line of code, rather than using a simple tool *naively supported*. There's just no reason to do that for a case like this. – Servy Feb 23 '16 at 17:30
  • @Servy, no, I'm saying that one should prefer using built-in functionality over reinventing the wheel, *especially* when the question is about migrating from another language. .NET offers more async programming techniques than Python's `async`. What would require hand coding in Python, may be available already in .NET – Panagiotis Kanavos Feb 24 '16 at 08:31
  • @Panagiotis Kanavos: The Python stuff was solved differently. It is triggered by another program which is started in .NET by commandline. So thank you all for your ideas... Regards! Akram – a_hamm99 Feb 24 '16 at 12:26