我正在使用下面的代码片段尝试运行作业(由用户从UI中选择)从主线程(异步)和同时互相干扰,并设置一些限制以防止占用过多RAM的所有RAM 。我使用了许多来源,例如ActionBlock
上的Stephen Cleary blog,this链接以及@ i3arnon中的this
public class ActionBlockJobsAsyncImpl {
private ActionBlock<Job> qJobs;
private Dictionary<Job, CancellationTokenSource> cTokSrcs;
public ActionBlockJobsAsyncImpl () {
qJobs = new ActionBlock<Job>(
async a_job => await RunJobAsync(a_job),
new ExecutionDataflowBlockOptions
{
BoundedCapacity = boundedCapacity,
MaxDegreeOfParallelism = maxDegreeOfParallelism,
});
cTokSrcs = new Dictionary<Job, CancellationTokenSource>();
}
private async Task<bool> RunJobAsync(Job a_job) {
JobArgs args = JobAPI.GetJobArgs(a_job);
bool ok = await JobAPI.RunJobAsync(args, cTokSrcs[a_job].Token);
return ok;
}
private async Task Produce(IEnumerable<Job> jobs) {
foreach (var job in jobs)
{
await qJobs.SendAsync(job);
}
//qJobs.Complete();
}
public override async Task SubmitJobs(IEnumerable<Job> jobs) {
//-Establish new cancellation token and task status
foreach (var job in jobs) {
cTokSrcs[job] = new CancellationTokenSource();
}
// Start the producer.
var producer = Produce(jobs);
// Wait for everything to complete.
await Task.WhenAll(producer);
}
}
我评论qJobs.Complete()
方法调用的原因是因为用户应该能够从UI(相同或不同的)连续提交作业,并且我在第一次使用中从实现和测试中学到了BufferBlock
如果我想要这样一个连续的生产者/消费者队列,我就不应该Complete()
调用BufferBlock
。但是我所学到的ActionBlock
并不支持运行并发作业;因此,这是我用ActionBlock
代替的第二次传递。
在使用SubmitJobs
的上述代码中,当用户选择要从UI运行的作业和点击时,会调用int
方法。 boundedCapacity=8
参数maxDegreeOfParallelism=DataflowBlockOptions.Unbounded
和BufferBlock
但是代码原样,目前什么都不做(也就是说,它没有运行任何作业) - 我的类似{{1}}实现另一方面,用于至少异步地运行作业,尽管彼此依次相互作用。在这里,它从不运行任何工作,我也没有看到任何错误消息。欣赏关于我做错的任何想法,以及关于如何解决问题的一些有用的想法。谢谢你的兴趣。