工厂模式到实例分拣机可以安全地进行多线程?

时间:2011-07-20 00:14:29

标签: c# .net multithreading factory-pattern

首先是良好工厂模式? 更新:否 - ISorter在技术上不符合工厂模式的正确定义
给出以下界面:

public interface ISorter
{
    ISorter Initialize(IEnumerable<int> Source);
    void Sort( );

    string Name { get; }
    IEnumerable<int> SortedList { get; }
}

...和3个分拣机 - InsertionSort,MergeSort和QuickSort。以下是使用MergeSort的实现:

[Export(typeof(ISorter))]
public class MergeSorter : ISorter
{
    int[] leftArray;
    int[] rightArray;

    private MergeSorter(IEnumerable<int> source)
    {
        //  independent copies of array
        leftArray = source.ToArray( );
        rightArray = source.ToArray( );
    }

    public ISorter Initialize(IEnumerable<int> Source)
    {
        return new MergeSorter(Source);
    }

    public void Sort( )
    {   /* call merge sort method */   }

    //    assume the rest of ISorter is implemented
    //    as well as the main Sort( ... ) method
}  

InsertionSortQuickSort类遵循相同的模式。当然,SortController完全不知道它甚至控制着哪些Sorters。它只是为任何前端感兴趣的提供SorterNames列表。现在,我的问题围绕着ISorter.Initialize( )的实施。我正在返回一个新的实例化ISorter对象,内部数组已初始化。目的是SortController可以处理多个请求以实例化多个分拣机;另外,Sort方法将通过SortController.StartSorter ( )方法执行:

public static void StartSorter(string SorterName, IEnumerable<int> Source)
{
    //  find ISorter by name and initialize
    //  'sorters' is an internal SorterCollection initialized from MEF discovery
    ISorter sorter = sorters.Sorters
                            .Where(key => key.Name == SorterName)
                            .FirstOrDefault( )
                            .Initialize(Source);

    if (sorter == null)
    { return; }

    SortInfo info = new SortInfo
    {
        Collection = sorter.SortedList,
        Invoker = sorter.Sort, //   delegate for asynchronous execution
        Sorter = sorter,
        Timer = new System.Diagnostics.Stopwatch( )
    };

    info.Timer.Start( );
    info.Invoker.BeginInvoke(new AsyncCallback(SortCompleted), info);

    RunningSorters.Add(sorter);
}

然后在回调中,您将看到我的唯一事件定义如下:

public static event EventHandler<SortCompletedEventArgs> OnSortCompleted = delegate { };

static void SortCompleted ( IAsyncResult iaResult )
{
    //  retrieve SortInfo object from IAsyncResult
    var info = (SortInfo)iaResult.AsyncState;

    //  delegate - EndInvoke
    info.Invoker.EndInvoke ( iaResult );

    //  raise event
    OnSortCompleted ( info, new SortCompletedEventArgs ( info ) );

    //  remove from running sorters list
    RunningSorters.Remove(info.Sorter);
}

这是MEF的良好工厂模式吗?这是一个线程安全且稳定的实现,能够处理多个分拣机(例如,每个分拣机最多100,000个整数)?

修改
注意:MergeSorter要求将原始数组拆分为2个数组;因此leftArrayrightArray。一旦分配了数组,我们就完成了Source,它应该可以自由更改 我使用的3种排序算法是示范库 - 而不是我自己的。我自己的排序例程将使用Compare方法 由于这是一个使用MEF的可扩展SortController,所有排序算法都有公共的无参数构造函数来满足实例化需求。

1 个答案:

答案 0 :(得分:2)

IMO,Factory假设您要返回一个类型的实例。我不太确定这是代码实际上做的。我可能错了,所以请纠正我的逻辑。

1)工厂界面应简单,仅负责创建ISorter的名称并不表示它是工厂

2)ISorter Initialize(IEnumerable<int> Source);我认为返回当前接口实例的方法不是最好的做法,你在这里面临某种无限递归

3)IEnumerable<int> SortedList { get; }名称表明它是一个排序列表,实际上是.NET中的type name。此类代码可能会使其他开发人员感到困惑

4)MergeSorter > constructor包含两个数组副本 - 一个数组需要两倍的内存,这会使内存消耗增加一倍(这实际上是否需要这种排序算法?)

5)它不是线程安全的,因为您正在将ToArray()用于同一个数组(进入两个私有字段)。那里没有同步,因此数组可能会在这两个调用之间发生变化,导致令人讨厌的异常

总结

我建议:

1)瘦而专用的工厂界面

2)将排序功能移至实施IComparer

3)这需要进行大量的重构,因此如果此代码有效,只需添加复制/删除/修改数组的锁(以使其保证线程安全)并删除(如果可能)重复的副本