Является ли ExpandoObject потокобезопасным? - PullRequest
1 голос
/ 16 апреля 2019

Простой вопрос, но документы молчат. В источниках есть некоторые блокировки, поэтому вероятно это так, но я хочу знать наверняка.

Может быть, есть существующий ответ, прежде чем я попытался написать тест? Если нет, как бы выглядел такой тест (я не уверен, что именно я должен тестировать, чтобы ответить, если он поточно-ориентированный или нет)?

Справочная информация: я использую CSharpScript для запуска пользовательских сценариев, где globals будет содержать dynamic свойства (ExpandoObject экземпляры). Эти свойства будут содержать используемые в сценариях методы (Action<T>), добавляемые и удаляемые динамически из другого потока. Это обеспечит пользователю более приятный синтаксис: ExpandoProperty.BlaBlaBla(parameters); по сравнению с использованием, например. словарь: DictionaryProperty["BlaBlaBla"](parameters);

Ответы [ 2 ]

2 голосов
/ 16 апреля 2019

ExpandoObject реализует интерфейс коллекции IDictionary<string,Object>, и, как вы видели реализацию , у него есть внутренние методы TryGetValue, TryAddValue, TryAddMember и * 1009.* аналогично ConcurrentDictionary для добавления динамических свойств и значений.Также он использует механизм блокировки для операций обновления элементов коллекции.Это кажется мне безопасным.

0 голосов
/ 16 апреля 2019

Если вы начали выполнять метод для объекта expando в одном потоке и удалить этот метод в другом потоке, то он работает нормально:

dynamic a = new ExpandoObject();
a.Action1 = (Action)(() => 
{ 
    Console.WriteLine("Action1 Start"); 
    Thread.Sleep(1000); 
    Console.WriteLine("Action1 End");
});



Task task1 = Task.Factory.StartNew(() => 
{ 
    a.Action1(); 
});

Task task2 = Task.Factory.StartNew(() => 
{ 
    ((IDictionary<String, Object>)a).Remove("Action1");
    Console.WriteLine("Action1 Removed");
});


Task.WaitAll(task1, task2);

Вот еще один пример, когда метод постоянно добавляется и удаляется из объекта expando в одном потоке и вызывается в другом потоке. Исключение выдается здесь только при отсутствии метода:

dynamic a = new ExpandoObject();

Task task1 = Task.Factory.StartNew(() =>
{
    while(true) 
    {
        a.Action1 = (Action)(() => { Thread.Sleep(10); });
        Thread.Sleep(100);
        ((IDictionary<String, Object>)a).Remove("Action1");
        Thread.Sleep(100);
    }
});

Task task2 = Task.Factory.StartNew(() => 
{
    while(true)
    {
        try 
        {
            a.Action1();
            Console.WriteLine("Action1");
            Thread.Sleep(20);
        }
        catch(Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
});

Конечно, вам нужно убедиться, что код внутри метода объекта expando поточно-ориентирован.

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