Skip to content

Commit e1b008f

Browse files
committed
feat: 本地化字符串和interface文件加载从单线程改为多线程
1 parent 3c4c702 commit e1b008f

File tree

7 files changed

+54
-17
lines changed

7 files changed

+54
-17
lines changed

VModer.Core/Services/GameResource/Base/CommonResourcesService.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ public abstract class CommonResourcesService<TType, TContent> : ResourcesService
1111
protected CommonResourcesService(
1212
string folderOrFileRelativePath,
1313
WatcherFilter filter,
14-
PathType pathType = PathType.Folder
14+
PathType pathType = PathType.Folder,
15+
bool isAsyncLoading = false
1516
)
16-
: base(folderOrFileRelativePath, filter, pathType) { }
17+
: base(folderOrFileRelativePath, filter, pathType, isAsyncLoading) { }
1718

1819
///<inheritdoc />
1920
protected abstract override TContent? ParseFileToContent(Node rootNode);

VModer.Core/Services/GameResource/Base/ResourcesService.cs

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Collections.Concurrent;
12
using System.Diagnostics;
23
using Microsoft.Extensions.DependencyInjection;
34
using NLog;
@@ -12,7 +13,7 @@ public abstract partial class ResourcesService<TType, TContent, TParseResult> :
1213
/// <summary>
1314
/// key: 文件路径, value: 文件内资源内容
1415
/// </summary>
15-
protected readonly Dictionary<string, TContent> Resources;
16+
protected readonly IDictionary<string, TContent> Resources;
1617
protected readonly Logger Log;
1718

1819
private readonly SettingsService _settingService;
@@ -25,7 +26,13 @@ public abstract partial class ResourcesService<TType, TContent, TParseResult> :
2526
/// <param name="folderOrFileRelativePath">文件夹或文件的相对路径</param>
2627
/// <param name="filter">过滤条件</param>
2728
/// <param name="pathType"><c>folderOrFileRelativePath</c>的类型</param>
28-
protected ResourcesService(string folderOrFileRelativePath, WatcherFilter filter, PathType pathType)
29+
/// <param name="isAsyncLoading">是否多线程加载资源, 子类需要确保重写的方法是线程安全的</param>
30+
protected ResourcesService(
31+
string folderOrFileRelativePath,
32+
WatcherFilter filter,
33+
PathType pathType,
34+
bool isAsyncLoading = false
35+
)
2936
{
3037
_folderOrFileRelativePath = folderOrFileRelativePath;
3138
Log = LogManager.GetLogger(typeof(TType).FullName);
@@ -42,13 +49,23 @@ protected ResourcesService(string folderOrFileRelativePath, WatcherFilter filter
4249
: [gameResourcesPathService.GetFilePathPriorModByRelativePath(folderOrFileRelativePath)];
4350

4451
// Resources 必须在使用 ParseFileAndAddToResources 之前初始化
45-
Resources = new Dictionary<string, TContent>(filePaths.Length);
46-
47-
SortFilePath(filePaths);
52+
if (isAsyncLoading)
53+
{
54+
Resources = new ConcurrentDictionary<string, TContent>();
55+
}
56+
else
57+
{
58+
Resources = new Dictionary<string, TContent>(filePaths.Length);
59+
}
4860

49-
foreach (string filePath in filePaths)
61+
if (isAsyncLoading)
5062
{
51-
ParseFileAndAddToResources(filePath);
63+
ParseFileAndAddToResourcesAsync(filePaths);
64+
}
65+
else
66+
{
67+
SortFilePath(filePaths);
68+
ParseFileAndAddToResourcesSync(filePaths);
5269
}
5370

5471
watcherService.Watch(
@@ -63,11 +80,29 @@ protected ResourcesService(string folderOrFileRelativePath, WatcherFilter filter
6380
}
6481

6582
/// <summary>
66-
/// 当需要对传入的文件路径顺序进行排序时, 重写此方法
83+
/// 当需要对传入的文件路径顺序进行排序时, 重写此方法, 在多线程加载资源时不调用.
6784
/// </summary>
6885
/// <param name="filePathArray"></param>
6986
protected virtual void SortFilePath(string[] filePathArray) { }
7087

88+
private void ParseFileAndAddToResourcesAsync(string[] filePaths)
89+
{
90+
var tasks = new List<Task>();
91+
foreach (string filePath in filePaths)
92+
{
93+
tasks.Add(Task.Run(() => ParseFileAndAddToResources(filePath)));
94+
}
95+
Task.WaitAll(tasks);
96+
}
97+
98+
private void ParseFileAndAddToResourcesSync(string[] filePaths)
99+
{
100+
foreach (string filePath in filePaths)
101+
{
102+
ParseFileAndAddToResources(filePath);
103+
}
104+
}
105+
71106
[Conditional("DEBUG")]
72107
private void LogItemsSum()
73108
{

VModer.Core/Services/GameResource/BuildingsService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace VModer.Core.Services.GameResource;
1010
public sealed class BuildingsService
1111
: CommonResourcesService<BuildingsService, FrozenDictionary<string, BuildingInfo>>
1212
{
13-
private Dictionary<string, FrozenDictionary<string, BuildingInfo>>.ValueCollection Buildings =>
13+
private ICollection<FrozenDictionary<string, BuildingInfo>> Buildings =>
1414
Resources.Values;
1515
private const string BuildingsKeyword = "buildings";
1616

VModer.Core/Services/GameResource/LeaderTraitsService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public sealed class LeaderTraitsService()
1414
WatcherFilter.Text
1515
)
1616
{
17-
private Dictionary<string, FrozenDictionary<string, LeaderTrait>>.ValueCollection Traits =>
17+
private ICollection<FrozenDictionary<string, LeaderTrait>> Traits =>
1818
Resources.Values;
1919

2020
public bool TryGetValue(string traitName, [NotNullWhen(true)] out LeaderTrait? trait)

VModer.Core/Services/GameResource/Localization/LocalizationService.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace VModer.Core.Services.GameResource.Localization;
1212
public sealed class LocalizationService
1313
: ResourcesService<LocalizationService, FrozenDictionary<string, string>, YAMLLocalisationParser.LocFile>
1414
{
15-
private Dictionary<string, FrozenDictionary<string, string>>.ValueCollection Localisations =>
15+
private ICollection<FrozenDictionary<string, string>> Localisations =>
1616
Resources.Values;
1717
private readonly LocalizationKeyMappingService _localizationKeyMapping;
1818

@@ -24,7 +24,8 @@ public LocalizationService(LocalizationKeyMappingService localizationKeyMapping)
2424
App.Services.GetRequiredService<SettingsService>().GameLanguage.ToGameLocalizationLanguage()
2525
),
2626
WatcherFilter.LocalizationFiles,
27-
PathType.Folder
27+
PathType.Folder,
28+
true
2829
)
2930
{
3031
_localizationKeyMapping = localizationKeyMapping;

VModer.Core/Services/GameResource/SpriteService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ public sealed class SpriteService
1515
{
1616
[Time("加载界面图片")]
1717
public SpriteService()
18-
: base("interface", WatcherFilter.GfxFiles) { }
18+
: base("interface", WatcherFilter.GfxFiles, PathType.Folder, true) { }
1919

20-
private Dictionary<string, FrozenDictionary<string, SpriteInfo>>.ValueCollection Sprites =>
20+
private ICollection<FrozenDictionary<string, SpriteInfo>> Sprites =>
2121
Resources.Values;
2222

2323
public bool TryGetSpriteInfo(string spriteTypeName, [NotNullWhen(true)] out SpriteInfo? info)

VModer.Core/Services/GameResource/TerrainService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace VModer.Core.Services.GameResource;
1111
/// </summary>
1212
public sealed class TerrainService : CommonResourcesService<TerrainService, FrozenSet<string>>
1313
{
14-
private Dictionary<string, FrozenSet<string>>.ValueCollection Terrains => Resources.Values;
14+
private ICollection<FrozenSet<string>> Terrains => Resources.Values;
1515

1616
/// <summary>
1717
/// 未在文件中定义的地形

0 commit comments

Comments
 (0)