2013-06-08 3 views
27

У меня есть «класс сценария» в IronPython, а скриптинг в моем приложении работает, вызывая методы на его экземпляре. Мне нужно реализовать сценарии вызова из нескольких потоков. Каков правильный способ сделать это?Многопоточность в IronPython

У меня есть несколько проблем:

  1. Is ScriptScope потокобезопасной? Информация противоречива. ScriptScope's documentation says: «ScriptScope не является потокобезопасным. Хост должен либо блокироваться, когда несколько потоков могут обращаться к одному модулю, либо сделать копию для каждого потока». Однако IronRuby использует те же DLR и @JimmySchementi says, что «ScriptRuntime, ScriptEngine и ScriptScope - все поточно-безопасные, предназначенные для использования между потоками. В частности, ScriptScope использует потокобезопасное хранилище данных, поэтому ScriptScope можно разделить между потоками «.

  2. Если я создаю несколько ScriptScope s, это будет означать выполнение одного и того же сценария инициализации несколько раз. Предположим, что я запускаю десять файлов сценариев Python, импортирую пять сборок и в целом выполняю совсем немного кода, чтобы получить «объект сценария». Есть ли способ избежать затрат времени и памяти на запуск большого количества одного и того же кода для каждого потока?

  3. ли сделать ScriptScope переменная нить статическим (то есть, применяя ThreadStaticAttribute) и выполнение инициализации для каждого потока, который утилизируется Task.Run путем? Или я должен использовать TaskScheduler с лимитом параллелизма, потому что стоимость нескольких областей высока?

В целом: , как правильно реализовать работает один и тот же сценарий, по разным аргументам в несколько потоков? Скрипты должны выполняться одновременно и не должны вылетать из-за условий гонки.

+3

Я чувствую к вам. Я обнаружил, что документация на Ironpthon и Ironruby отсутствует во всех аспектах, так как Microsoft прекратила официально поддерживать ее. –

ответ

-1

Так как это не похоже на то, что вы получаете конкретный ответ, у меня есть общий.

Мой коллега использовал IronPhython в моей предыдущей работе и обработке многопоточности было бы очень важно, поэтому я могу сказать, что можно запустить IronPython в многопоточной среде в производственной системе.

Я не знаю, использовал ли он свой собственный замок или зависел от блокировки внутри IronPython.

Я хотел бы предложить:

а) Выполнить тесты самостоятельно. Вы должны написать простой тест, чтобы доказать, что это безопасно или нет. Кое-что столь же грубый, как следующий код, может быть хорошим началом:

[Test] 
    public void TwoThreadsWithTheirOwnContexts() { 
     //Create two threads 
     var tasks = new Task[2]; 
     tasks[0] = Task.Factory.StartNew(PrintSomethingInIronPython1); 
     tasks[1] = Task.Factory.StartNew(PrintSomethingInIronPython2); 
     Task.WaitAll(tasks); 
    } 

b) Добавить шлюзы в любом случае. Возможно, не большая проблема с блокировкой в ​​коде, и вы устраните неопределенность.

В конечном счете, если документы говорят, что что-то не является потокобезопасным, вам придется либо доказать, что это (тест), либо играть безопасно (ваша собственная блокировка). Независимо от того, что нужно делать многопоточные тесты, прежде чем вы входите в производство. Я не думаю, что вы действительно теряете время, делая их в начале.

Re 2: Опять предложение. Создайте потоки пулов, которые инициализируют один раз, а затем повторно используют эти потоки.

+2

Я не думаю, что безопасность нитей может быть проверена модульными испытаниями. –

+0

@JeffreyZhao Согласитесь - безопасность потока - это неотъемлемое качество чего-то, а не единицы теста. – data

2

1.

Если документация ScriptScope говорит, что это не поточно, верите, или, по крайней мере, действовать, как вы это поверить. @JimmySchementi, возможно, рассмотрела текущую реализацию и выяснила, что она в настоящее время является потокобезопасной, но это не дает никаких гарантий того, как она будет вести себя в следующем патче класса, не говоря уже о следующем крупном выпуске.

2.

Да, вы должны инициализировать каждый из ваших ScriptScopes. Я попытался бы свести к минимуму количество требуемых ScriptScopes, как это сделать будет зависеть от вашей настройки. Если основной целью соответствующих потоков является размещение ScriptScope, тогда вы должны использовать ThreadPool с каждым потоком, имеющим один ThreadLocal < ScriptScope>. Если эти потоки выполняют другие действия, а также запущенные скрипты, тогда у вас должен быть пул объектов, в котором хранятся ScriptScopes, и каждый поток может проверить ScriptScopes, выполнить работу, а затем освободить ScriptScope.

3.

ThreadLocal Предпочитают над ThreadStatic, если вы идете по этому пути.

0

Так вы делаете это в сценариях, если я правильно вас понял.

https://github.com/dretax/Python-Plugins/blob/master/PlutonPlugins/PluIRC/PluIRC.py#L154

Посмотрите, что делает этот скрипт, он полностью запускает новую нить одно и то же, с различными аргументами.

Файл py, который вы можете увидеть, если ПОЛНОСТЬЮ нарезать резьбу и использует IronPython. Это КАК вы правильно делаете нити, а НЕ каким-либо другим способом.