8

Öncelikli bir ActionBlock<T> uygulamak istiyorum. Böylece Predicate<T> kullanarak bazı TInput öğelerine koşullu olarak öncelik verebilirim.
Parallel Extensions Extras Samples ve Guide to Implementing Custom TPL Dataflow Blocks belgelerini okudum.
Yine de bu senaryoyu nasıl uygulayabileceğimi anlamıyorum.
---------------------------- DÜZENLEME ------------------- --------
Aynı anda 5 tanesi çalıştırılabilen bazı görevler vardır. Kullanıcı düğmeye basıldığında, bazıları (yüklem işlevine bağlıdır) görevler en öncelikli olarak çalıştırılmalıdır. Aslında
ben bu koduÖzelleştirme ActionBlock <T>

TaskScheduler taskSchedulerHighPriority; 
ActionBlock<CustomObject> actionBlockLow; 
ActionBlock<CustomObject> actionBlockHigh; 
... 
queuedTaskScheduler = new QueuedTaskScheduler(TaskScheduler.Default, 5); 
taskSchedulerHigh = queuedTaskScheduler.ActivateNewQueue(0); 
taskSchedulerLow = queuedTaskScheduler.ActivateNewQueue(1); 
... 
actionBlockHigh = new ActionBlock<CustomObject>(new Action<CustomObject>(method), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 5, SingleProducerConstrained = false, TaskScheduler = taskSchedulerHigh }); 
actionBlockLow = new ActionBlock<CustomObject>(new Action<CustomObject>(method), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 5, MaxMessagesPerTask = 1, TaskScheduler = taskSchedulerLow }); 
...  
if (predicate(customObject)) 
    actionBlockHigh.Post(customObject); 
else 
    actionBlockLow.Post(customObject); 

yazmak Ama öncelik hiç etkilenmez almaz görünüyor.
---------------------------- DÜZENLEME ------------------

actionBlockHigh = new ActionBlock<AvlHistory>(new Action<AvlHistory>(SemaphoreAction), new ExecutionDataflowBlockOptions { TaskScheduler = taskSchedulerHigh }); 
actionBlockLow = new ActionBlock<AvlHistory>(new Action<AvlHistory>(SemaphoreAction), new ExecutionDataflowBlockOptions { TaskScheduler = taskSchedulerLow }); 

Nedeni uygulama doğru Görevler önceliklerini gözlemlemek ama sadece bir görev arada gösterilmektedir ilk kod bloğunu kullanarak, bir defada yürütmek edilebilir: Ben bu kod satırını kullandığınızda gerçeğini bulmak akan, neden uygulama 5 görevleri aynı anda ama uygun olmayan öncelik sırası çalıştırın.

actionBlockHigh = new ActionBlock<AvlHistory>(new Action<AvlHistory>(SemaphoreAction), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 5, TaskScheduler = taskSchedulerHigh }); 
actionBlockLow = new ActionBlock<AvlHistory>(new Action<AvlHistory>(SemaphoreAction), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 5, TaskScheduler = taskSchedulerLow }); 

Güncelleme:
Tanklar i taskSchedulerLow için MaxMessagesPerTask belirtmelidir, svick için.

+2

Önceliği belirleyen nedir? Hiç T ile ilgili olmayan bir şey mi? Ya da "T" nin içsel/türetilmiş bir özelliği önceliği var mıdır? – casperOne

+0

ConcurrentPriorityQueue kullanan özel bir arabellek bloğu oluşturabilir veya özel bir asenkronize transfromasyon bloğu oluşturabilirsiniz. Her iki seçenek de önemsizdir. Ayrıca, @casperOne ile aynı fikirdeyseniz, durumunuzda öncelik ne anlama geliyor? –

cevap

7

Sorunuz pek çok ayrıntı içermiyor, bu nedenle aşağıdakiler neye ihtiyacınız olabileceğini tahmin etmektir.

Bunu yapmanın en kolay yolu, QueuedTaskScheduler from ParallelExtensionsExtras numaralı telefonun farklı önceliklerinde çalışan iki ActionBlock s ürününe sahip olmaktır. Bir önceliği kullanarak yüksek öncelikli olanı ve daha sonra düşük öncelikli olanla bağlantı kurabilirsiniz. Ayrıca, yüksek öncelikli Task s'nin beklemediğinden emin olmak için düşük öncelikli bloğun MaxMessagesPerTask değerini ayarlayın.

Bu Ne yapabilirsin sadece bir kroki olduğu
static ITargetBlock<T> CreatePrioritizedActionBlock<T>(
    Action<T> action, Predicate<T> isPrioritizedPredicate) 
{ 
    var buffer = new BufferBlock<T>(); 

    var scheduler = new QueuedTaskScheduler(1); 

    var highPriorityScheduler = scheduler.ActivateNewQueue(0); 
    var lowPriorityScheduler = scheduler.ActivateNewQueue(1); 

    var highPriorityBlock = new ActionBlock<T>(
     action, new ExecutionDataflowBlockOptions 
     { 
      TaskScheduler = highPriorityScheduler 
     }); 
    var lowPriorityBlock = new ActionBlock<T>(
     action, new ExecutionDataflowBlockOptions 
     { 
      TaskScheduler = lowPriorityScheduler, 
      MaxMessagesPerTask = 1 
     }); 

    buffer.LinkTo(highPriorityBlock, isPrioritizedPredicate); 
    buffer.LinkTo(lowPriorityBlock); 

    return buffer; 
} 

, örneğin, iade bloğun Completion doğru davranmaz:

kodunda, bu gibi bir şey olacaktır.

+0

lütfen edited etiketini okuyun – Rzassar

+1

Kodunuzda, düşük öncelikli engellemeniz için 'MaxMessagesPerTask' belirtmezsiniz. Söylediğim gibi, bunu yapmak oldukça dengesiz. – svick