0

私は次の設定をしていますTransformBlock

private void SetupTestModule()
{
    Func<int, int> func1 = new Func<int, int>(input =>
        {
            return (input + 1);
        });

    Func<int, int> func2 = new Func<int, int>(input =>
        {
            return (input + 2);
        });

    TransformBlock<int, int> transform = new TransformBlock<int, int>(func1);
}

実行時にfunc1をfunc2に交換できるかどうか、およびこのtransformBlockと他のデータブロック間のすべてのリンクがそのまま残るかどうか疑問に思います。理想的には、Funcsを交換するときに、新しい変換をすべての新しく入ってくるアイテムに適用したいだけです。明らかに、この単純なアプローチでは、現在キューにあるアイテムとそれらの処理方法については想定していません。新しいFuncを割り当てると、ランタイムエラーが発生するのか、それともtransformBlockのリンクが解除されるのか疑問に思います。いくつかの洞察を共有できる人はいますか?

編集:Jonの提案を投稿し、ここにいくつかの非常に基本的なテストコードをコーディングします。私が興味を持っているのは、volatileキーワードがある場合とない場合で機能することです。なぜ必要なのvolatileですか?

public class TransformBlockHotSwap
{
    private TransformBlock<int, int> transformBlock;
    private ActionBlock<int> actionBlock;

    public TransformBlockHotSwap()
    {

        SwappableFunction<int, int> swappable = new SwappableFunction<int, int>(item => item + 1);
        transformBlock = new TransformBlock<int, int>(item => swappable.Execute(item));
        actionBlock = new ActionBlock<int>(item => Console.WriteLine(item));
        transformBlock.LinkTo(actionBlock);

        Func<int, int> func2 = new Func<int,int>(item => item * item);

        for (int index = 1; index <= 100; index++)
        {
            transformBlock.Post(index);

            Thread.Sleep(500);

            if (index == 5)
            {
                swappable.Swap(func2);
            }
        }
    }
}

public class SwappableFunction<TInput, TOutput>
{
    private Func<TInput, TOutput> func;

    public SwappableFunction(Func<TInput, TOutput> func)
    {
        this.func = func;
    }

    public void Swap(Func<TInput, TOutput> newFunc)
    {
        func = newFunc;
    }

    public TOutput Execute(TInput input)
    {
        return func(input);
    }
}

編集(述語スワッピングを含めるため):

public class TransformBlockHotSwap
{
    private TransformBlock<int, int> transformBlock;
    private ActionBlock<int> actionBlock;

    public TransformBlockHotSwap()
    {
        Func<int, int> defaultFunction = new Func<int, int>(item => item);
        Func<int, int> func2 = new Func<int, int>(item => item * item);
        Predicate<int> defaultPredicate = new Predicate<int>(item => true);
        Predicate<int> pred2 = new Predicate<int>(item =>
            {
                if (item % 2 == 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            });

        SwappableFunction<int, int> swappableFunction = new SwappableFunction<int, int>(defaultFunction);
        SwappablePredicate<int> swappablePredicate = new SwappablePredicate<int>(defaultPredicate);

        transformBlock = new TransformBlock<int, int>(item => swappableFunction.Execute(item));
        actionBlock = new ActionBlock<int>(item => Console.WriteLine(item));
        transformBlock.LinkTo(actionBlock, item => swappablePredicate.Execute(item));

        for (int index = 1; index <= 100; index++)
        {
            transformBlock.Post(index);

            if (index == 10)
            {
                swappablePredicate.Swap(pred2);
            }

            Thread.Sleep(200);
        }

        Console.WriteLine("Done");
        Console.ReadKey();
    }
}

public class SwappableFunction<TInput, TOutput>
{
    private volatile Func<TInput, TOutput> func;

    public SwappableFunction(Func<TInput, TOutput> defaultFunction)
    {
        this.func = defaultFunction;
    }

    public void Swap(Func<TInput, TOutput> newFunc)
    {
        func = newFunc;
    }

    public TOutput Execute(TInput input)
    {
        return func(input);
    }
}

public class SwappablePredicate<TInput>
{
    private volatile Predicate<TInput> predicate;

    public SwappablePredicate(Predicate<TInput> defaultPredicate)
    {
        this.predicate = defaultPredicate;
    }

    public void Swap(Predicate<TInput> newPredicate)
    {
        predicate = newPredicate;
    }

    public bool Execute(TInput input)
    {
        return predicate(input);
    }
}
4

1 に答える 1

3

私はあなたがそうすることができるとは思っていません-しかしあなたは委任する関数を簡単に書くことができます:

public class SwappableFunction<TInput, TOutput>
{
    private volatile Func<TInput, TOutput> func;

    public SwappableFunction(Func<TInput, TOutput> func)
    {
        this.func = func;
    }

    public void Swap(Func<TInput, TOutput> newFunc)
    {
        func = newFunc;
    }

    public TOutput Execute(TInput input)
    {
        return func(input);
    }
}

それで:

var swappable = new SwappableFunction<int, int>(input => input + 1);
var block = new TransformBlock<int, int>(swappable.Execute);
// Later...

swappable.Swap(input => input + 2);

重要-ここでの使用について100%確信が持てません-セマンティクスが混乱するため、volatile一般的に使用するのは好きではありません。volatile使用Interlocked.CompareExchangeする方が良い可能性がありますが、コードはかなり長くなるので、最初に要点を理解したかったのです:)

于 2013-02-16T08:59:01.150 に答える