【问题标题】:TaskScheduler with async sequential Tasks C#具有异步顺序任务 C# 的 TaskScheduler
【发布时间】:2016-02-24 17:35:59
【问题描述】:

我正在异步执行一些 .py 脚本。执行一个脚本大约需要 30 秒。可能会在两到三秒的时间跨度内选择两个甚至更多的脚本。目标是拥有一个调度程序,它收集所有任务并一个接一个地执行它们。应包括 FIFO 功能。 我尝试了以下代码只是为了尝试 queuedTaskScheduler 的功能,但即使这样也不起作用。

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

【问题讨论】:

  • 对于 FIFO 使用 Queue 类。对于 LIFO,请使用 Stack 类。
  • 启动此代码时,我看不到标签在一个接一个地执行任务时发生变化。

标签: c# c#-4.0


【解决方案1】:

我解决了。只需要一个信号量。与Thread中的方法相同 这是代码:

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

非常感谢!

【讨论】:

  • 混合信号量和任务是一种气味。如果您想一次执行一个“任务”,您可以使用 ActionBlock。事实上,您可以使用 TPL Dataflow 库创建具有不同并行度、负载平衡等的完整数据流管道
  • @PanagiotisKanavos 在这里使用Semaphore 没有任何问题。它专门专为这种确切类型的用例而设计。如果您想要更高级的功能,TPL 数据流可以,但如果您不需要它,那么这很好。
  • @Servy 在 [tpl-dataflow] 中存在一个问题,其中 SemaphoreSlim 实际上导致块阻塞。 SemaphoreSlim 不是原生构造,并且在后台使用了几个技巧。至于简单/高级,有了ActionBlock,你只需要var block=new ActionBlock&lt;MyMessageType&gt;(msg=&gt;Process(msg));就可以开始排队工作了。
  • @PanagiotisKanavos 那么你声称使用两者一起存在问题,而不是单独使用任何一个来解决问题。巨大差距。而且您建议在程序中安装一个完整的第 3 方工具只是为了添加那一行代码,而不是使用天真支持的简单工具。对于这种情况,没有理由这样做。
  • @Servy,不,我是说人们应该更喜欢使用内置功能而不是重新发明轮子,尤其是当问题是关于从另一种语言迁移时。 .NET 提供了比 Python 的 async 更多的异步编程技术。需要在 Python 中手动编码的内容可能已经在 .NET 中提供了
猜你喜欢
  • 2011-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-07
  • 2017-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多