具有异步顺序任务的TaskScheduler C#
我正在异步执行一些.py脚本。一个脚本执行大约需要30秒。在两三秒钟的时间跨度内,可能会选择两个或更多脚本。目标是拥有一个调度器,它收集所有任务并逐个执行。应包括FIFO功能。 我尝试了以下代码,只是为了尝试queuedTaskScheduler的功能,但即使这样也不起作用具有异步顺序任务的TaskScheduler C#,c#,c#-4.0,C#,C# 4.0,我正在异步执行一些.py脚本。一个脚本执行大约需要30秒。在两三秒钟的时间跨度内,可能会选择两个或更多脚本。目标是拥有一个调度器,它收集所有任务并逐个执行。应包括FIFO功能。 我尝试了以下代码,只是为了尝试queuedTaskScheduler的功能,但即使这样也不起作用 QueuedTaskScheduler queueScheduler; private TaskScheduler ts_priority1; int pos = 0; public Form1()
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);
}
QueuedTaskScheduler-queueScheduler;
专用任务调度器ts_优先级1;
int pos=0;
公共表格1()
{
初始化组件();
queueScheduler=新的QueuedTaskScheduler(targetScheduler:TaskScheduler.Default,maxConcurrencyLevel:1);
ts_priority1=queueScheduler.ActivateNewQueue(1);
}
私有无效按钮3\u单击(对象发送者,事件参数e)
{
队列值(位置、优先级1);
pos++;
}
私有无效按钮4_单击(对象发送者,事件参数e)
{
更改字符串(pos);
pos++;
}
私有无效更改字符串(int位置)
{
var bea=“这是线程”+位置+“开始”;
MethodInvoker Labelupdate=委托
{
label2.Text=bea;
};
调用(Labelupdate);
睡眠(3000);
bea=“线程”+位置+“正在结束”;
MethodInvoker Labelupdate1=委托
{
label2.Text=bea;
};
调用(Labelupdate1);
睡眠(1000);
}
私有void updateLabel(字符串实验室)
{
MethodInvoker Labelupdate=委托
{
label2.Text=Lab;
};
调用(Labelupdate);
}
专用任务队列任务(函数f,任务调度器ts)
{
返回Task.Factory.StartNew(f,CancellationToken.None,TaskCreationOptions.HidesScheduler | TaskCreationOptions.Denychildatach,ts);
}
专用任务队列值(int位置,TaskScheduler ts)
{
返回队列任务(异步()=>
{
label2.Text=“这是线程”+位置+“开始”;
睡眠(3000);
label2.Text=“线程”+位置+“正在结束”;
睡眠(1000);
},ts);
}
我解决了它。只需要一个信号灯。这和这个一样
代码如下:
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);
}
非常感谢 对于FIFO,请使用队列类。对于后进先出,使用堆栈类。当启动此代码时,我看不到标签在一个接一个地执行任务时发生变化。混合信号量和任务是一种气味。如果您想一次执行一个“任务”,可以使用ActionBlock。事实上,您可以使用TPL数据流创建具有不同并行度、负载平衡等的整个数据流管道library@PanagiotisKanavos在这里使用
信号灯
完全没有问题。它是专门为这种类型的用例设计的。TPL数据流如果可以,如果您想要更高级的功能,但如果您不需要它,那么这就可以了。@Servy[TPL Dataflow]中存在一个问题,其中信号量LIM实际上会导致阻塞。SemaphoreSlim不是一个本地构造,它在幕后使用了一些技巧。对于简单/高级的ActionBlock,您只需要var block=newActionBlock(msg=>Process(msg))
然后您就可以开始排队工作了。@PanagiotisKanavos那么您是在声称两者一起使用存在问题,而不是单独使用其中一个来解决问题。差别很大。你建议在程序中安装一个完整的第三方工具只是为了添加一行代码,而不是使用一个简单的工具。对于这样的情况,没有理由这么做。@Servy,不,我是说人们应该更喜欢使用内置功能而不是重新发明轮子,特别是当问题是从另一种语言迁移时。NET提供了比Python的async
更多的异步编程技术。需要用Python手工编码的东西可能已经在.NET中提供了