修复因重复注册cancellationToken.Register导致的内存暴涨!

This commit is contained in:
Kimdiego2098
2023-09-15 13:17:36 +08:00
parent b21a4e1a4d
commit 166ac2307a
5 changed files with 387 additions and 3 deletions

View File

@@ -0,0 +1,141 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在XREF结尾的命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// API首页http://rrqm_home.gitee.io/touchsocket/
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace TouchSocket.Core
{
/// <summary>
/// 等待数据对象
/// </summary>
/// <typeparam name="T"></typeparam>
public class WaitDataEx<T> : DisposableObject, IWaitData<T>
{
private readonly AutoResetEvent m_waitHandle;
private volatile WaitDataStatus m_status;
/// <summary>
/// WaitData
/// </summary>
public WaitDataEx()
{
this.m_waitHandle = new AutoResetEvent(false);
}
/// <inheritdoc/>
public WaitDataStatus Status { get => this.m_status; }
/// <inheritdoc/>
public T WaitResult { get; private set; }
/// <inheritdoc/>
public void Cancel()
{
this.m_status = WaitDataStatus.Canceled;
this.m_waitHandle.Set();
}
/// <inheritdoc/>
public void Reset()
{
this.m_status = WaitDataStatus.Default;
this.WaitResult = default;
this.m_waitHandle.Reset();
}
/// <inheritdoc/>
public bool Set()
{
this.m_status = WaitDataStatus.SetRunning;
return this.m_waitHandle.Set();
}
/// <inheritdoc/>
public bool Set(T waitResult)
{
this.WaitResult = waitResult;
this.m_status = WaitDataStatus.SetRunning;
return this.m_waitHandle.Set();
}
CancellationTokenRegistration registration = default;
/// <inheritdoc/>
public void SetCancellationToken(CancellationToken cancellationToken)
{
if (registration == default)
{
if (cancellationToken.CanBeCanceled)
registration = cancellationToken.Register(this.Cancel);
}
else
{
registration.Dispose();
if (cancellationToken.CanBeCanceled)
registration = cancellationToken.Register(this.Cancel);
}
}
/// <inheritdoc/>
public void SetResult(T result)
{
this.WaitResult = result;
}
/// <summary>
/// 等待指定时间
/// </summary>
/// <param name="timeSpan"></param>
public WaitDataStatus Wait(TimeSpan timeSpan)
{
return this.Wait((int)timeSpan.TotalMilliseconds);
}
/// <summary>
/// 等待指定毫秒
/// </summary>
/// <param name="millisecond"></param>
public WaitDataStatus Wait(int millisecond)
{
if (!this.m_waitHandle.WaitOne(millisecond))
{
this.m_status = WaitDataStatus.Overtime;
}
return this.m_status;
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
this.m_status = WaitDataStatus.Disposed;
this.WaitResult = default;
this.m_waitHandle.SafeDispose();
base.Dispose(disposing);
}
}
/// <summary>
/// 等待数据对象
/// </summary>
public class WaitDataEx : WaitData<object>
{
}
}

View File

@@ -0,0 +1,132 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace TouchSocket.Core
{
/// <summary>
/// 等待数据对象
/// </summary>
/// <typeparam name="T"></typeparam>
public class WaitDataExAsync<T> : DisposableObject, IWaitData<T>
{
private readonly AsyncAutoResetEvent m_asyncWaitHandle;
private volatile WaitDataStatus m_status;
/// <summary>
/// 构造函数
/// </summary>
public WaitDataExAsync()
{
this.m_asyncWaitHandle = new AsyncAutoResetEvent(false);
}
/// <inheritdoc/>
public WaitDataStatus Status { get => this.m_status; }
/// <inheritdoc/>
public T WaitResult { get; private set; }
/// <inheritdoc/>
public void Cancel()
{
this.m_status = WaitDataStatus.Canceled;
this.m_asyncWaitHandle.Set();
}
/// <inheritdoc/>
public void Reset()
{
this.m_status = WaitDataStatus.Default;
this.WaitResult = default;
this.m_asyncWaitHandle.Reset();
}
/// <inheritdoc/>
public bool Set()
{
this.m_status = WaitDataStatus.SetRunning;
return this.m_asyncWaitHandle.Set();
}
/// <inheritdoc/>
public bool Set(T waitResult)
{
this.WaitResult = waitResult;
this.m_status = WaitDataStatus.SetRunning;
return this.m_asyncWaitHandle.Set();
}
CancellationTokenRegistration registration = default;
/// <inheritdoc/>
public void SetCancellationToken(CancellationToken cancellationToken)
{
if (registration == default)
{
if (cancellationToken.CanBeCanceled)
registration = cancellationToken.Register(this.Cancel);
}
else
{
registration.Dispose();
if (cancellationToken.CanBeCanceled)
registration = cancellationToken.Register(this.Cancel);
}
}
/// <inheritdoc/>
public void SetResult(T result)
{
this.WaitResult = result;
}
/// <summary>
/// 等待指定时间
/// </summary>
/// <param name="timeSpan"></param>
/// <returns></returns>
public async Task<WaitDataStatus> WaitAsync(TimeSpan timeSpan)
{
if (!await this.m_asyncWaitHandle.WaitOneAsync(timeSpan))
{
this.m_status = WaitDataStatus.Overtime;
}
return this.m_status;
}
/// <summary>
/// 等待指定毫秒
/// </summary>
/// <param name="millisecond"></param>
public Task<WaitDataStatus> WaitAsync(int millisecond)
{
return this.WaitAsync(TimeSpan.FromMilliseconds(millisecond));
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
this.m_status = WaitDataStatus.Disposed;
this.WaitResult = default;
this.m_asyncWaitHandle.SafeDispose();
base.Dispose(disposing);
}
}
/// <summary>
/// 等待数据对象
/// </summary>
public class WaitDataExAsync : WaitDataAsync<object>
{
}
}

View File

@@ -20,8 +20,8 @@ internal class WaitingClientEx<TClient> : DisposableObject, IWaitingClient<TClie
{
private readonly Func<ResponsedData, bool> m_func;
private readonly EasyLock easyLock = new();
private readonly WaitData<ResponsedData> m_waitData = new();
private readonly WaitDataAsync<ResponsedData> m_waitDataAsync = new();
private readonly WaitDataEx<ResponsedData> m_waitData = new();
private readonly WaitDataExAsync<ResponsedData> m_waitDataAsync = new();
private volatile bool m_breaked;

View File

@@ -13,7 +13,7 @@
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="TouchSocket" Version="2.0.0-beta.163" />
<PackageReference Include="TouchSocket" Version="2.0.0-beta.176" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'!='net45'">
<PackageReference Include="System.IO.Ports" Version="7.0.0" />

View File

@@ -2745,5 +2745,116 @@
<member name="M:ThingsGateway.Foundation.ThingsGatewayBitConverter.ToUInt64(System.Byte[],System.Int32,System.Int32)">
<inheritdoc/>
</member>
<member name="T:TouchSocket.Core.WaitDataEx`1">
<summary>
等待数据对象
</summary>
<typeparam name="T"></typeparam>
</member>
<member name="M:TouchSocket.Core.WaitDataEx`1.#ctor">
<summary>
WaitData
</summary>
</member>
<member name="P:TouchSocket.Core.WaitDataEx`1.Status">
<inheritdoc/>
</member>
<member name="P:TouchSocket.Core.WaitDataEx`1.WaitResult">
<inheritdoc/>
</member>
<member name="M:TouchSocket.Core.WaitDataEx`1.Cancel">
<inheritdoc/>
</member>
<member name="M:TouchSocket.Core.WaitDataEx`1.Reset">
<inheritdoc/>
</member>
<member name="M:TouchSocket.Core.WaitDataEx`1.Set">
<inheritdoc/>
</member>
<member name="M:TouchSocket.Core.WaitDataEx`1.Set(`0)">
<inheritdoc/>
</member>
<member name="M:TouchSocket.Core.WaitDataEx`1.SetCancellationToken(System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:TouchSocket.Core.WaitDataEx`1.SetResult(`0)">
<inheritdoc/>
</member>
<member name="M:TouchSocket.Core.WaitDataEx`1.Wait(System.TimeSpan)">
<summary>
等待指定时间
</summary>
<param name="timeSpan"></param>
</member>
<member name="M:TouchSocket.Core.WaitDataEx`1.Wait(System.Int32)">
<summary>
等待指定毫秒
</summary>
<param name="millisecond"></param>
</member>
<member name="M:TouchSocket.Core.WaitDataEx`1.Dispose(System.Boolean)">
<inheritdoc/>
</member>
<member name="T:TouchSocket.Core.WaitDataEx">
<summary>
等待数据对象
</summary>
</member>
<member name="T:TouchSocket.Core.WaitDataExAsync`1">
<summary>
等待数据对象
</summary>
<typeparam name="T"></typeparam>
</member>
<member name="M:TouchSocket.Core.WaitDataExAsync`1.#ctor">
<summary>
构造函数
</summary>
</member>
<member name="P:TouchSocket.Core.WaitDataExAsync`1.Status">
<inheritdoc/>
</member>
<member name="P:TouchSocket.Core.WaitDataExAsync`1.WaitResult">
<inheritdoc/>
</member>
<member name="M:TouchSocket.Core.WaitDataExAsync`1.Cancel">
<inheritdoc/>
</member>
<member name="M:TouchSocket.Core.WaitDataExAsync`1.Reset">
<inheritdoc/>
</member>
<member name="M:TouchSocket.Core.WaitDataExAsync`1.Set">
<inheritdoc/>
</member>
<member name="M:TouchSocket.Core.WaitDataExAsync`1.Set(`0)">
<inheritdoc/>
</member>
<member name="M:TouchSocket.Core.WaitDataExAsync`1.SetCancellationToken(System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:TouchSocket.Core.WaitDataExAsync`1.SetResult(`0)">
<inheritdoc/>
</member>
<member name="M:TouchSocket.Core.WaitDataExAsync`1.WaitAsync(System.TimeSpan)">
<summary>
等待指定时间
</summary>
<param name="timeSpan"></param>
<returns></returns>
</member>
<member name="M:TouchSocket.Core.WaitDataExAsync`1.WaitAsync(System.Int32)">
<summary>
等待指定毫秒
</summary>
<param name="millisecond"></param>
</member>
<member name="M:TouchSocket.Core.WaitDataExAsync`1.Dispose(System.Boolean)">
<inheritdoc/>
</member>
<member name="T:TouchSocket.Core.WaitDataExAsync">
<summary>
等待数据对象
</summary>
</member>
</members>
</doc>