SORU
5 Temmuz 2013, Cuma


Uygulama yinelenebilir bir bloğunun tamamlanması doğru

Teaserçocuklar, bu soru politikasını yeniden uygulamak hakkında değil. VUK veri akışı bloğu hakkında doğru tamamlanması.

Bu soru genelde benim önceki soru Retry policy within ITargetBlock bir devamıdır. Bu sorunun cevabı @TransformBlock (kaynağı) ve TransformManyBlock (hedef) kullanan svick akıllı çözüm oldu. Tek sorun, Sol bir bu bloğu tamamlamak içindoğru yolu: tüm deneme ilk tamamlanması için bekleyin ve hedef blok tamamlayın. (Sadece bir parçasında, olmayan iş parçacığı için güvenli retries bir set için çok fazla önem verme) ile sona erdi:

var retries = new HashSet<RetryingMessage<TInput>>();

TransformManyBlock<RetryableMessage<TInput>, TOutput> target = null;
target = new TransformManyBlock<RetryableMessage<TInput>, TOutput>(
    async message =>
    {
        try
        {
            var result = new[] { await transform(message.Data) };
            retries.Remove(message);
            return result;
        }
        catch (Exception ex)
        {
            message.Exceptions.Add(ex);
            if (message.RetriesRemaining == 0)
            {
                if (failureHandler != null)
                    failureHandler(message.Exceptions);

                retries.Remove(message);
            }
            else
            {
                retries.Add(message);
                message.RetriesRemaining--;

                Task.Delay(retryDelay)
                    .ContinueWith(_ => target.Post(message));
            }
            return null;
        }
    }, dataflowBlockOptions);

source.LinkTo(target);

source.Completion.ContinueWith(async _ =>
{
    while (target.InputCount > 0 || retries.Any())
        await Task.Delay(100);

    target.Complete();
});

Fikri yoklama çeşit gerçekleştirmek ve hala işlenmek üzere bekleyen iletiler olup olmadığını doğrulamak için yeniden deneniyor gerektiren bir mesaj var. Ama bu çözüm yoklama fikri hoşuma gitmiyor.

Evet, ben saklanması mantığı ekleme/çıkarma deneme ayrı bir sınıf ve hatta örneğin bazı eylemleri gerçekleştirmek için denemeleri olur boş, ama nasıl davranılması target.InputCount > 0 durum? Blok için bekleyen mesaj varsa denilen gibi bir geri arama yok, hayır, küçük bir gecikme ile bir döngü içinde target.ItemCount doğrulama sadece bir seçenek gibi görünüyor.

Herkes akıllı bir şekilde bunu başarmak için biliyor mu?

CEVAP
7 EKİM 2013, PAZARTESİ


Belki ManualResetEvent sizin için hile yapabilir.

TransformManyBlock ortak bir özellik ekleyin

private ManualResetEvent _signal  = new ManualResetEvent(false);
public ManualResetEvent Signal { get { return _signal; } }

Ve işte burada:

var retries = new HashSet<RetryingMessage<TInput>>();

TransformManyBlock<RetryableMessage<TInput>, TOutput> target = null;
target = new TransformManyBlock<RetryableMessage<TInput>, TOutput>(
    async message =>
    {
        try
        {
            var result = new[] { await transform(message.Data) };
            retries.Remove(message);

            // Sets the state of the event to signaled, allowing one or more waiting threads to proceed
            if(!retries.Any()) Signal.Set(); 
            return result;
        }
        catch (Exception ex)
        {
            message.Exceptions.Add(ex);
            if (message.RetriesRemaining == 0)
            {
                if (failureHandler != null)
                    failureHandler(message.Exceptions);

                retries.Remove(message);

                // Sets the state of the event to signaled, allowing one or more waiting threads to proceed
                if(!retries.Any()) Signal.Set(); 
            }
            else
            {
                retries.Add(message);
                message.RetriesRemaining--;

                Task.Delay(retryDelay)
                    .ContinueWith(_ => target.Post(message));
            }
            return null;
        }
    }, dataflowBlockOptions);

source.LinkTo(target);

source.Completion.ContinueWith(async _ =>
{
    //Blocks the current thread until the current WaitHandle receives a signal.
    target.Signal.WaitOne();

    target.Complete();
});

target.InputCount set nerede emin değilim. Yerde target.InputCount değiştirmek çok aşağıdaki kodu ekleyebilirsiniz:

if(InputCount == 0)  Signal.Set();

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Chuck Testa

    Chuck Testa

    14 AĞUSTOS 2011
  • Nightmare2005

    Nightmare200

    14 Ocak 2007
  • PhoneArena

    PhoneArena

    7 NİSAN 2006