用于知道何时可以在新线程中调用方法的模式



我有一个Device接口:

public interface IDevice
{
    double Measure();
}

一些实现该接口的类有一个测量仪器:

public class InstrumentedDevice : IDevice
{
    public MeasuringInstrument Instrument { get; set; }
    public double Measure()
    {
        if (Instrument != null)
            return Instrument.DoMeasuring();
        return 0;
    }
}

我想根据Instrument属性对InstrumentedDevice的实例进行分组,这样结果就是组的集合,其中每个设备都使用与其组中所有其他设备相同的仪器。

然后,我想为每组启动一个新线程,并并行执行测量。

看起来像这样:

public void MeasureAllDevices(IEnumerable<InstrumentedDevice> devices)
{
    var groups = devices.GroupBy(d => d.Instrument);
    foreach (var gr in groups)
    {
        var bgw = new BackgroundWorker();
        bgw.DoWork += (s, e) =>
        {
            foreach (var device in gr)
            {
                device.Measure();
            }
        };
        bgw.RunWorkerAsync();        
    }
}

问题是我没有得到InstrumentedDevice的集合作为MeasureAllDevices的参数。我得到了IDevice:的集合

public void MeasureAllDevices(IEnumerable<IDevice> devices)
{
}

我的问题是:有没有一种模式可以用来解决我的问题?并非所有设备都具有MeasuringInstrument,并且一些设备可能具有不同的方法来确定它们是否可以并行测量。

我想在IDevice接口中添加一些内容,比如CanBeMultiThreadedWith(IDevice other),但我不确定它是如何工作的。

public interface IDevice
{
    string GroupBy {get;}
    double Measure();
}

好的,我的第一个答案误解了这个问题。这是一个新的:

public interface IDevice
{
    double Measure();
    string ConcurrencyGroupName { get; }
}

每个设备都有一个新的"并发组名称"。惯例是,只有具有相同名称的设备才能并行处理。

所以你.group通过ConcurrencyGroupName和foreach组并行处理其项。

通过这种方式,设备决定是否要并行执行。进行处理的核心代码永远不需要修改。

InstrumentedDevice类只会返回仪器的名称或其ID作为ConcurrencyGroupName。其他实现也是可能的。

您需要将设备分为已插入指令的设备和未插入指令的:

var measurable = devices.OfType<InstrumentedDevice>().ToList();
var notMeasurable = devices.Except(measurable).ToList();

您可以独立处理这两个集合。

public static MeasuringInstrument Instrument(this IDevice device)
{
  if (device is InstrumentedDevice)
  {
    return (device as InstrumentedDevice).Instrument;
  }
  return null;
}

var groups = devices.GroupBy(d => d.Instrument());
foreach (var gr in groups) 

最新更新