Как входят в пользовательский Ориентированный на многопотоковое исполнение Универсальный Список возвратить целый список в C#?

Я - новичок поточной обработки, и я пытаюсь записать пользовательский ориентированный на многопотоковое исполнение универсальный класс списка в C# (.NET 3,5 SP1). Я читал, Почему ориентированные на многопотоковое исполнение наборы настолько трудно?. После рассмотрения требований класса я думаю, что только должен безопасно добавить к списку и возвратить список. Пример показывает в значительной степени все, что я хочу кроме него, испытывает недостаток в методе списка возврата поэтому, я записал свой собственный открытый метод как ниже:

Обновление: на основе предложений, учитывая я рассмотрел свои требования и поэтому упростил класс до как указано ниже:

public sealed class ThreadSafeList
{
    private readonly IList list = new List();
    private readonly object lockable = new object();

    public void Add(T t)
    {
        lock (lockable)
        {
            list.Add(t);
        }
    }

    public IList GetSnapshot()
    {
        IList result;
        lock (lockable)
        {
            result = new List(list);
        }
        return result;
    }
}

5
задан Jeff 25 February 2010 в 04:40
поделиться

3 ответа

Согласитесь с @jrista. Необходимо решить проблему семантики, и почему она называется Translate () ? Какова цель?

A - текущий код - вернуть оболочку внутреннего списка, доступную только для чтения

return new ReadOnlyCollection<T>(list);

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

B - копия только для чтения.

return new List<T>(list).AsReadOnly();

Этот список не имеет проблем с потоками, потому что ничто не изменяет новый список. Единственная ссылка содержится в оболочке ReadOnlyCollection .

C - обычная (доступная для записи) копия

return new List<T>(list);

Возвращает новый список, и вызывающий может делать со своим списком все, что они хотят, не затрагивая исходный список, и изменения в исходном списке не влияют на этот список.


Имеет ли значение, если другой потребитель берет копию списка и затем изменяет свою копию? Нужно ли потребителям видеть изменения в списке? Вам просто нужен поточно-безопасный перечислитель?

public IEnumerator<T> ThreadSafeEnumerator()
{
    List<T> copy;
    lock(lockable)
        copy = new List<T>(list);

    foreach (var value in copy)
        yield return value;
}
2
ответ дан 14 December 2019 в 19:11
поделиться

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

1
ответ дан 14 December 2019 в 19:11
поделиться

Если вы хотите загрузить ресурсы из того же протокола, с которым загружена страница, то ее использование является идеальным способом ее выполнения. Однако вам может понадобиться загрузить некоторые ресурсы с http , даже если ваша страница в настоящее время обслуживается в https (допустим, ресурс обслуживается только на http или вы предпочитаете уменьшить нагрузку на ваш сервер, не заставляя его шифровать каждый образ на странице). В этом случае необходимо явно указать имя протокола.

-121--3995657-

Делает ByteArrayOutputStream.close () действительно освободить память?

Нет. Абсолютно ничего не делает. Вы можете посмотреть на его исходный код:

public void close() throws IOException {
}

Чтобы освободить память, убедитесь, что нет никаких ссылок на нее и пусть Garbage Collector делает свою вещь. Как и с любым другим нормальным объектом.

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

-121--1019448-

Метод Translate () выглядит правильно. Используя блокировку, вы запрещаете другим добавлять или иным образом изменять список во время работы в Translate/AddRange.

Я думаю, что может быть проблема с вашей собственностью IsReadyOnly. При внутреннем чтении/записи свойства используется блокировка. Но есть и публичный геттер, который не заперт. Возможно, поток 1 вызывает MarkAsReadOnly, в то время как второй поток может получить значение false при просмотре IsReadOnly. Вместо этого я бы использовал нормальное свойство и либо заблокировал бы его, либо использовал летучее поле.

1
ответ дан 14 December 2019 в 19:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: