Шаблон для определения, когда метод может быть вызван в новом потоке - PullRequest
0 голосов
/ 02 февраля 2012

У меня есть 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;
    }
}

Я хотел бы сгруппировать экземпляры InstrumentedDevice в соответствии с их свойством Instrument, чтобы в результате был получен набор групп, в которых каждое устройство использует тот же инструмент, что и все другие устройства в его группе. *

Затем я хотел бы запустить новый поток для каждой группы и выполнить измерение параллельно.

Это будет выглядеть примерно так:

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), но я не уверен, как это будет работать.

Ответы [ 4 ]

1 голос
/ 02 февраля 2012

Хорошо, мой первый ответ неправильно понял проблему. Вот новый:

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

Каждое устройство получает новое «имя группы параллелизма». Соглашение состоит в том, что только устройство, которое имеет такое же имя, может обрабатываться параллельно.

Таким образом, вы .GroupBy ConcurrencyGroupName и foreach группа обрабатывает его элементы параллельно.

Таким образом, устройства решают, хотят ли они работать параллельно или нет. Ваш центральный фрагмент кода, который выполняет обработку, никогда не будет изменен.

Ваш класс InstrumentedDevice просто возвращает имя инструмента или его идентификатор в качестве ConcurrencyGroupName. Возможны и другие реализации.

1 голос
/ 02 февраля 2012
public interface IDevice
{
    string GroupBy {get;}
    double Measure();
}
0 голосов
/ 02 февраля 2012
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) 
0 голосов
/ 02 февраля 2012

Вам необходимо разделить устройства на инструментированные и неподходящие:

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

Вы можете обрабатывать два набора независимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...