Skip to content

Commit

Permalink
critical bug fix and improvement
Browse files Browse the repository at this point in the history
- fix multiple memory leaks in the DownloadHelper.cs
- implement Dispose() for serval classes
- reduce memory usage
- increase download speed
- optimize code
  • Loading branch information
laolarou726 committed Nov 23, 2021
1 parent 6c7d419 commit f77c535
Show file tree
Hide file tree
Showing 22 changed files with 604 additions and 494 deletions.
3 changes: 0 additions & 3 deletions ProjBobcat/.editorconfig
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
[*.cs]

# CA1063: 正确实现 IDisposable
dotnet_diagnostic.CA1063.severity = silent

dotnet_diagnostic.CS1591.severity = suggestion

dotnet_diagnostic.CA2007.severity = none
Expand Down
48 changes: 17 additions & 31 deletions ProjBobcat/ProjBobcat/Class/Helper/DownloadHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,10 @@ public static async Task AdvancedDownloadListFile(IEnumerable<DownloadFile> file
var filesBlock =
new TransformManyBlock<IEnumerable<DownloadFile>, DownloadFile>(d =>
{
var dl = d.ToList();
foreach (var df in dl.Where(df => !Directory.Exists(df.DownloadPath)))
foreach (var df in d.Where(df => !Directory.Exists(df.DownloadPath)))
Directory.CreateDirectory(df.DownloadPath);
return dl;
return d;
});

var actionBlock = new ActionBlock<DownloadFile>(async d =>
Expand Down Expand Up @@ -143,28 +141,23 @@ public static async Task DownloadData(DownloadFile downloadProperty, Cancellatio
tSpeed += speed;
cSpeed++;

downloadProperty.Changed?.Invoke(null,
new DownloadFileChangedEventArgs
{
ProgressPercentage = (double)downloadedBytesCount / responseLength,
BytesReceived = downloadedBytesCount,
TotalBytes = responseLength,
Speed = speed
});
downloadProperty.OnChanged(
speed,
(double)downloadedBytesCount / responseLength,
downloadedBytesCount,
responseLength);
}

sw.Stop();
fileToWriteTo.Close();
stream.Close();

var aSpeed = tSpeed / cSpeed;
downloadProperty.Completed?.Invoke(null,
new DownloadFileCompletedEventArgs(true, null, downloadProperty, aSpeed));
downloadProperty.OnCompleted(true, null, aSpeed);
}
catch (Exception e)
{
downloadProperty.Completed?.Invoke(null,
new DownloadFileCompletedEventArgs(false, e, downloadProperty, 0));
downloadProperty.OnCompleted(false, e, 0);
}
}

Expand Down Expand Up @@ -356,14 +349,11 @@ public static async Task MultiPartDownloadTaskAsync(DownloadFile downloadFile, i
tSpeed += speed;
cSpeed++;
downloadFile.Changed?.Invoke(t,
new DownloadFileChangedEventArgs
{
ProgressPercentage = (double)downloadedBytesCount / responseLength,
BytesReceived = downloadedBytesCount,
TotalBytes = responseLength,
Speed = speed
});
downloadFile.OnChanged(
speed,
(double)downloadedBytesCount / responseLength,
downloadedBytesCount,
responseLength);
}
sw.Stop();
Expand Down Expand Up @@ -403,8 +393,7 @@ await writeActionBlock.Completion.ContinueWith(async task =>
{
var ex = task.Exception ?? new AggregateException(new Exception("没有完全下载所有的分片"));
downloadFile.Completed?.Invoke(task,
new DownloadFileCompletedEventArgs(false, ex, downloadFile, aSpeed));
downloadFile.OnCompleted(false, ex, aSpeed);
if (File.Exists(filePath))
File.Delete(filePath);
Expand All @@ -426,8 +415,7 @@ await writeActionBlock.Completion.ContinueWith(async task =>
}
outputStream.Close();
downloadFile.Completed?.Invoke(null,
new DownloadFileCompletedEventArgs(true, null, downloadFile, aSpeed));
downloadFile.OnCompleted(true, null, aSpeed);
}, cts.Token);

streamBlock.Complete();
Expand All @@ -440,9 +428,7 @@ await writeActionBlock.Completion.ContinueWith(async task =>
foreach (var piece in readRanges.Where(piece => File.Exists(piece.TempFileName)))
File.Delete(piece.TempFileName);

downloadFile.Completed?.Invoke(null,
new DownloadFileCompletedEventArgs(false, ex, downloadFile, 0));

downloadFile.OnCompleted(false, ex, 0);
}
}

Expand Down
79 changes: 58 additions & 21 deletions ProjBobcat/ProjBobcat/Class/LaunchWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Diagnostics;
using ProjBobcat.Class.Model;
using ProjBobcat.Class.Model.Auth;
using ProjBobcat.DefaultComponent.Launch.GameCore;
using ProjBobcat.Event;
using ProjBobcat.Interface;

Expand All @@ -12,6 +13,8 @@ namespace ProjBobcat.Class
/// </summary>
public class LaunchWrapper : IDisposable
{
bool disposedValue;

/// <summary>
/// 构造函数
/// </summary>
Expand Down Expand Up @@ -41,10 +44,6 @@ public LaunchWrapper(AuthResultBase authResult)
/// </summary>
public Process Process { get; init; }

public void Dispose()
{
}

/// <summary>
/// 执行过程
/// </summary>
Expand Down Expand Up @@ -73,11 +72,14 @@ void ProcessOnErrorDataReceived(object sender, DataReceivedEventArgs e)
{
if (string.IsNullOrEmpty(e.Data)) return;

GameCore.LogGameData(sender, new GameLogEventArgs
if (GameCore is GameCoreBase coreBase)
{
LogType = GameLogType.Unknown,
RawContent = e.Data
});
coreBase.OnLogGameData(sender, new GameLogEventArgs
{
LogType = GameLogType.Unknown,
RawContent = e.Data
});
}
}

void ProcessOnOutputDataReceived(object sender, DataReceivedEventArgs e)
Expand All @@ -94,13 +96,16 @@ void ProcessOnOutputDataReceived(object sender, DataReceivedEventArgs e)
var exceptionMsg = GameCore.GameLogResolver.ResolveExceptionMsg(e.Data);
var stackTrace = GameCore.GameLogResolver.ResolveStackTrace(e.Data);

GameCore.LogGameData(sender, new GameLogEventArgs
if(GameCore is GameCoreBase gameCoreBase)
{
LogType = type,
RawContent = e.Data,
StackTrace = stackTrace,
ExceptionMsg = exceptionMsg
});
gameCoreBase.OnLogGameData(sender, new GameLogEventArgs
{
LogType = type,
RawContent = e.Data,
StackTrace = stackTrace,
ExceptionMsg = exceptionMsg
});
}

return;
}
Expand All @@ -109,14 +114,46 @@ void ProcessOnOutputDataReceived(object sender, DataReceivedEventArgs e)
var source = GameCore.GameLogResolver.ResolveSource(totalPrefix);


GameCore.LogGameData(sender, new GameLogEventArgs
if (GameCore is GameCoreBase coreBase)
{
coreBase.OnLogGameData(sender, new GameLogEventArgs
{
LogType = type,
RawContent = e.Data,
Content = e.Data[(totalPrefix?.Length ?? 0)..],
Source = source,
Time = time
});
}
}

protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
LogType = type,
RawContent = e.Data,
Content = e.Data[(totalPrefix?.Length ?? 0)..],
Source = source,
Time = time
});
if (disposing)
{
Process?.Dispose();
}

// TODO: 释放未托管的资源(未托管的对象)并重写终结器
// TODO: 将大型字段设置为 null
disposedValue = true;
}
}

// // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
// ~LaunchWrapper()
// {
// // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
// Dispose(disposing: false);
// }

public void Dispose()
{
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
84 changes: 81 additions & 3 deletions ProjBobcat/ProjBobcat/Class/Model/DownloadFile.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using System;
using System.ComponentModel;
using ProjBobcat.Event;

namespace ProjBobcat.Class.Model
{
/// <summary>
/// 下载文件信息类
/// </summary>
public class DownloadFile : ICloneable
public class DownloadFile : ICloneable, IDisposable
{
/// <summary>
/// 下载Uri
Expand Down Expand Up @@ -56,12 +57,59 @@ public class DownloadFile : ICloneable
/// <summary>
/// 下载完成事件
/// </summary>
public EventHandler<DownloadFileCompletedEventArgs> Completed { get; set; }
public event EventHandler<DownloadFileCompletedEventArgs> Completed
{
add
{
listEventDelegates.AddHandler(CompletedEventKey, value);
}
remove
{
listEventDelegates.RemoveHandler(CompletedEventKey, value);
}
}

/// <summary>
/// 下载改变事件
/// </summary>
public EventHandler<DownloadFileChangedEventArgs> Changed { get; set; }
public event EventHandler<DownloadFileChangedEventArgs> Changed
{
add
{
listEventDelegates.AddHandler(ChangedEventKey, value);
}
remove
{
listEventDelegates.RemoveHandler(ChangedEventKey, value);
}
}

protected EventHandlerList listEventDelegates = new ();

bool disposedValue;
static readonly object CompletedEventKey = new ();
static readonly object ChangedEventKey = new();

public void OnChanged(double speed, double progress, long bytesReceived, long totalBytes)
{
var eventList = listEventDelegates;
var @event = (EventHandler<DownloadFileChangedEventArgs>)eventList[ChangedEventKey];
@event?.Invoke(this, new DownloadFileChangedEventArgs
{
Speed = speed,
ProgressPercentage = progress,
BytesReceived = bytesReceived,
TotalBytes = totalBytes
});
}

public void OnCompleted(bool? success, Exception ex, double averageSpeed)
{
var eventList = listEventDelegates;
var test = eventList[CompletedEventKey];
var @event = (EventHandler<DownloadFileCompletedEventArgs>)eventList[CompletedEventKey];
@event?.Invoke(this, new DownloadFileCompletedEventArgs(success, ex, averageSpeed));
}

public object Clone()
{
Expand All @@ -78,5 +126,35 @@ public object Clone()
TimeOut = TimeOut
};
}

protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: 释放托管状态(托管对象)
listEventDelegates.Dispose();
}

// TODO: 释放未托管的资源(未托管的对象)并重写终结器
// TODO: 将大型字段设置为 null
disposedValue = true;
}
}

// // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
// ~DownloadFile()
// {
// // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
// Dispose(disposing: false);
// }

public void Dispose()
{
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ public async Task<AuthResultBase> AuthTaskAsync(bool userField = false)
}
}

using var resultJson = await HttpHelper.Post(LoginAddress, requestJson).ConfigureAwait(true);
var content = await resultJson.Content.ReadAsStringAsync().ConfigureAwait(true);
using var resultJson = await HttpHelper.Post(LoginAddress, requestJson);
var content = await resultJson.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<AuthResponseModel>(content);

if (result == default || string.IsNullOrEmpty(result.AccessToken))
Expand Down Expand Up @@ -305,8 +305,8 @@ public async Task<AuthResultBase> AuthRefreshTaskAsync(AuthResponseModel respons
};
var requestJson = JsonConvert.SerializeObject(requestModel, JsonHelper.CamelCasePropertyNamesSettings);

using var resultJson = await HttpHelper.Post(RefreshAddress, requestJson).ConfigureAwait(true);
var content = await resultJson.Content.ReadAsStringAsync().ConfigureAwait(true);
using var resultJson = await HttpHelper.Post(RefreshAddress, requestJson);
var content = await resultJson.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<object>(content);

switch (result)
Expand Down Expand Up @@ -388,7 +388,7 @@ public async Task<bool> ValidateTokenTaskAsync(string accessToken)
};
var requestJson = JsonConvert.SerializeObject(requestModel, JsonHelper.CamelCasePropertyNamesSettings);

using var result = await HttpHelper.Post(ValidateAddress, requestJson).ConfigureAwait(true);
using var result = await HttpHelper.Post(ValidateAddress, requestJson);
return result.StatusCode.Equals(HttpStatusCode.NoContent);
}

Expand All @@ -401,7 +401,7 @@ public async Task TokenRevokeTaskAsync(string accessToken)
};
var requestJson = JsonConvert.SerializeObject(requestModel, JsonHelper.CamelCasePropertyNamesSettings);

using var x = await HttpHelper.Post(RevokeAddress, requestJson).ConfigureAwait(true);
using var x = await HttpHelper.Post(RevokeAddress, requestJson);
}

/// <summary>
Expand All @@ -418,7 +418,7 @@ public async Task<bool> SignOutTaskAsync()
};
var requestJson = JsonConvert.SerializeObject(requestModel, JsonHelper.CamelCasePropertyNamesSettings);

using var result = await HttpHelper.Post(SignOutAddress, requestJson).ConfigureAwait(true);
using var result = await HttpHelper.Post(SignOutAddress, requestJson);
return result.StatusCode.Equals(HttpStatusCode.NoContent);
}
}
Expand Down
Loading

0 comments on commit f77c535

Please sign in to comment.