Объекты, добавленные в словарь другим потоком, не отрисованные OpenTK - PullRequest
0 голосов
/ 15 декабря 2018

В настоящее время я работаю над клоном minecraft, и сейчас я пытаюсь реализовать многопоточность, с которой я никогда не работал (я читал некоторые документы от Microsoft, но это все), чтобы генерировать порции без зависания игры.второй.

Мой класс World хранит словарь (System.Collections.Generic) блоков, каждый из которых содержит трехмерный массив идентификаторов блоков.В моем методе Update я добавляю новые чанки, которые должны быть сгенерированы, в очередь (работает по назначению), и у меня есть другой поток, который должен обрабатывать очередь и генерировать чанки один за другим:

World class:)

Dictionary<Vector2, Chunk> chunks = new Dictionary<Vector2, Chunk>();
Queue<Vector2> chunksToCreate = new Queue<Vector2>();

public World(Chunk.ChunkGen generator, int program, int seed) {
    generatorFunc = generator;
    Program = program;
    Seed = seed;
    chunksCreator = new Thread(CreateChunks);
    chunksCreator.Start();
}

private void CreateChunks() {
    while (true) {
        if (chunksToCreate.Count == 0)
            continue;
        Vector2 vec = chunksToCreate.First();
        chunks[vec] = generatorFunc(this, (int)vec.X, (int)vec.Y);
        chunksToCreate.TryDequeue(out Vector2 outVec);
    }
}

Моя проблема в том, что, когда я создаю чанки, просто вызывая generatorFunc (делегат), они добавляются в словарь и отрисовываются opentk, как и ожидалось, но когда ясоздать с этим другим потоком, они также добавляются в словарь, и в отладчике VS все внутри объектов выглядит правильно, НО они вообще не отображаются.

Я уже пытался использовать ConcurrentQueue и ConcurrentDictionary но без изменений.

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

1 Ответ

0 голосов
/ 15 декабря 2018

Пользовательский интерфейс не любит графические объекты, созданные в других потоках.Например, если ваши чанки содержат кисти, они могут не работать в потоке пользовательского интерфейса, если они были созданы в рабочем потоке.

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

private void CreateChunks() {
    while (chunksToCreate.TryDequeue(out Vector2 vec)) {
        chunks.TryAdd(vec, generatorFunc(this, (int)vec.X, (int)vec.Y));
    }
}

Но с помощью * 1007 можно избежать создания нужного количества потоков и управления ими самостоятельно.* Task Parallel Library (TPL) .

Parallel.ForEach(chunksToCreate, vec =>
    chunks.TryAdd(vec, generatorFunc(this, (int)vec.X, (int)vec.Y))
);

Обратите внимание, что источник chunksToCreate не должен быть потокобезопасным, поскольку Parallel.ForEach назначает элементы потокам перед их запуском;однако, словарь chunks должен, так как он будет доступен для нескольких потоков параллельно.


ConcurrentDictionary<Vector2, Chunk> chunks = new ConcurrentDictionary<Vector2, Chunk>();
List<Vector2> chunksToCreate = new List<Vector2>();

public World(Chunk.ChunkGen generator, int program, int seed) {
    Program = program;
    Seed = seed;
    Parallel.ForEach(chunksToCreate, vec =>
        chunks.TryAdd(vec, generator(this, (int)vec.X, (int)vec.Y))
    );
}
...