mirror of
https://github.com/RRQM/TouchSocket.git
synced 2025-12-19 01:46:44 +08:00
发布:3.1.7
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<BaseVersion>3.1.6</BaseVersion>
|
||||
<BaseVersion>3.1.7</BaseVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<TouchSocketVersion>$(BaseVersion)</TouchSocketVersion>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace TouchSocket.Core;
|
||||
@@ -37,4 +38,13 @@ public static class GlobalEnvironment
|
||||
public static bool IsDynamicCodeSupported => true;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// 获取应用程序的基础目录。
|
||||
/// </summary>
|
||||
public static string BaseDirectory =>
|
||||
#if NET45
|
||||
AppDomain.CurrentDomain.BaseDirectory;
|
||||
#else
|
||||
AppContext.BaseDirectory;
|
||||
#endif
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public sealed class FileLogger : LoggerBase, IDisposable
|
||||
// 表达式的结果是根据当前日期格式化后的字符串,确保每天的日志被打包在不同的文件夹中
|
||||
this.m_createLogFolder = (logLevel) =>
|
||||
{
|
||||
return Path.Combine("logs", DateTime.Now.ToString("[yyyy-MM-dd]"));
|
||||
return Path.Combine(GlobalEnvironment.BaseDirectory, "logs", DateTime.Now.ToString("[yyyy-MM-dd]"));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -17,20 +17,36 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TouchSocket.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 表示动态方法的信息。
|
||||
/// </summary>
|
||||
public interface IDynamicMethodInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 真实返回值类型。
|
||||
/// <para>当方法为void或task时,为null</para>
|
||||
/// <para>当方法为task泛型时,为泛型元素类型</para>
|
||||
/// <para>当方法为 void 或 Task 时,为 null。</para>
|
||||
/// <para>当方法为 Task 泛型时,为泛型元素类型。</para>
|
||||
/// </summary>
|
||||
Type RealReturnType { get;}
|
||||
Type RealReturnType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 返回值的Task类型。
|
||||
/// 返回值的 Task 类型。
|
||||
/// </summary>
|
||||
MethodReturnKind ReturnKind { get;}
|
||||
MethodReturnKind ReturnKind { get; }
|
||||
|
||||
object Invoke(object instance, object[] parameters);
|
||||
/// <summary>
|
||||
/// 异步获取方法的结果。
|
||||
/// </summary>
|
||||
/// <param name="result">方法的返回值。</param>
|
||||
/// <returns>异步任务,包含方法的结果。</returns>
|
||||
Task<object> GetResultAsync(object result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 调用方法。
|
||||
/// </summary>
|
||||
/// <param name="instance">方法所属的实例对象。</param>
|
||||
/// <param name="parameters">方法的参数。</param>
|
||||
/// <returns>方法的返回值。</returns>
|
||||
object Invoke(object instance, object[] parameters);
|
||||
}
|
||||
@@ -25,7 +25,6 @@ public class FileResourceInfo : PackageBase
|
||||
{
|
||||
private FileSection[] m_fileSections;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 初始化FileResourceInfo对象的新实例。
|
||||
/// </summary>
|
||||
@@ -41,7 +40,7 @@ public class FileResourceInfo : PackageBase
|
||||
}
|
||||
|
||||
// 使用FileInfo对象创建RemoteFileInfo对象,并用其初始化FileResourceInfo对象
|
||||
this.Create(fileInfo.Map<RemoteFileInfo>(), fileSectionSize);
|
||||
this.PrivateCreate(fileInfo.Map<RemoteFileInfo>(), fileSectionSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -62,13 +61,14 @@ public class FileResourceInfo : PackageBase
|
||||
public FileResourceInfo(RemoteFileInfo fileInfo, int fileSectionSize)
|
||||
{
|
||||
// 调用Create方法来初始化远程资源,这是因为初始化过程可能涉及到复杂的逻辑,通过调用已有方法可以简化构造函数的代码
|
||||
this.Create(fileInfo, fileSectionSize);
|
||||
this.PrivateCreate(fileInfo, fileSectionSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从内存初始化资源
|
||||
/// </summary>
|
||||
/// <param name="byteBlock">包含资源信息的字节块</param>
|
||||
[Obsolete($"此方法已被弃用,请使用{nameof(FileResourceInfo.Create)}")]
|
||||
public FileResourceInfo(in IByteBlock byteBlock)
|
||||
{
|
||||
// 读取文件区块大小
|
||||
@@ -92,6 +92,10 @@ public class FileResourceInfo : PackageBase
|
||||
this.m_fileSections = fileSections;
|
||||
}
|
||||
|
||||
private FileResourceInfo()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源文件信息
|
||||
/// </summary>
|
||||
@@ -112,6 +116,58 @@ public class FileResourceInfo : PackageBase
|
||||
/// </summary>
|
||||
public int ResourceHandle { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 从字节块创建一个新的 <see cref="FileResourceInfo"/> 实例。
|
||||
/// </summary>
|
||||
/// <param name="byteBlock">字节块,用于读取文件资源信息。</param>
|
||||
/// <returns>返回一个新的 <see cref="FileResourceInfo"/> 实例。</returns>
|
||||
public static FileResourceInfo Create(ByteBlock byteBlock)
|
||||
{
|
||||
return Create(ref byteBlock);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从流中创建一个新的 <see cref="FileResourceInfo"/> 实例。
|
||||
/// </summary>
|
||||
/// <param name="stream">包含文件资源信息的流。</param>
|
||||
/// <returns>返回一个新的 <see cref="FileResourceInfo"/> 实例。</returns>
|
||||
public static FileResourceInfo Create(Stream stream)
|
||||
{
|
||||
return Create(new ByteBlock(stream.ReadAllToByteArray()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从字节块创建一个新的 <see cref="FileResourceInfo"/> 实例。
|
||||
/// </summary>
|
||||
/// <typeparam name="TByteBlock">字节块的类型,必须实现 <see cref="IByteBlock"/> 接口。</typeparam>
|
||||
/// <param name="byteBlock">引用的字节块,用于读取文件资源信息。</param>
|
||||
/// <returns>返回一个新的 <see cref="FileResourceInfo"/> 实例。</returns>
|
||||
public static FileResourceInfo Create<TByteBlock>(ref TByteBlock byteBlock) where TByteBlock : IByteBlock
|
||||
{
|
||||
var fileResourceInfo = new FileResourceInfo();
|
||||
// 读取文件区块大小
|
||||
fileResourceInfo.FileSectionSize = byteBlock.ReadInt32();
|
||||
// 读取资源句柄
|
||||
fileResourceInfo.ResourceHandle = byteBlock.ReadInt32();
|
||||
// 读取文件信息
|
||||
fileResourceInfo.FileInfo = byteBlock.ReadPackage<RemoteFileInfo>();
|
||||
// 读取文件区块数量
|
||||
var len = byteBlock.ReadInt32();
|
||||
|
||||
// 根据读取的文件区块数量,创建相应的 FileSection 数组
|
||||
var fileSections = new FileSection[len];
|
||||
// 遍历每个文件区块,并从字节块中读取具体信息
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
fileSections[i] = byteBlock.ReadPackage<FileSection>();
|
||||
}
|
||||
|
||||
// 将读取的文件区块信息数组赋值给成员变量
|
||||
fileResourceInfo.m_fileSections = fileSections;
|
||||
|
||||
return fileResourceInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取尝试续传时的索引。
|
||||
/// </summary>
|
||||
@@ -151,6 +207,7 @@ public class FileResourceInfo : PackageBase
|
||||
// 使用LINQ查询语法,筛选出所有Status为指定fileSectionStatus的FileSection对象
|
||||
return this.FileSections.Where(a => a.Status == fileSectionStatus);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Package<TByteBlock>(ref TByteBlock byteBlock)
|
||||
{
|
||||
@@ -173,35 +230,6 @@ public class FileResourceInfo : PackageBase
|
||||
this.ResourceHandle = handle;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Unpackage<TByteBlock>(ref TByteBlock byteBlock)
|
||||
{
|
||||
this.ResourceHandle = byteBlock.ReadInt32();
|
||||
this.FileInfo = byteBlock.ReadPackage<RemoteFileInfo>();
|
||||
}
|
||||
|
||||
private void Create(RemoteFileInfo fileInfo, long fileSectionSize)
|
||||
{
|
||||
this.ResourceHandle = this.GetHashCode();
|
||||
this.FileSectionSize = (int)fileSectionSize;
|
||||
var sectionCount = (int)((fileInfo.Length / fileSectionSize) + 1);
|
||||
var sections = new FileSection[sectionCount];
|
||||
for (var i = 0; i < sectionCount; i++)
|
||||
{
|
||||
var fileSection = new FileSection()
|
||||
{
|
||||
Offset = i * fileSectionSize,
|
||||
Length = (int)Math.Min(fileInfo.Length - i * fileSectionSize, fileSectionSize),
|
||||
ResourceHandle = this.ResourceHandle,
|
||||
Status = FileSectionStatus.Default,
|
||||
Index = i
|
||||
};
|
||||
sections[i] = fileSection;
|
||||
}
|
||||
this.FileInfo = fileInfo;
|
||||
this.m_fileSections = sections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将<see cref="FileResourceInfo"/>对象保存到内存。
|
||||
/// </summary>
|
||||
@@ -222,4 +250,56 @@ public class FileResourceInfo : PackageBase
|
||||
byteBlock.WritePackage(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将<see cref="FileResourceInfo"/>对象保存到内存。
|
||||
/// </summary>
|
||||
/// <param name="byteBlock">用于存储文件资源信息的字节块参数。</param>
|
||||
public void Save(ByteBlock byteBlock)
|
||||
{
|
||||
this.Save(ref byteBlock);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将 <see cref="FileResourceInfo"/> 对象保存到指定的流中。
|
||||
/// </summary>
|
||||
/// <param name="stream">目标流,用于存储文件资源信息。</param>
|
||||
public void Save(Stream stream)
|
||||
{
|
||||
using (var byteBlock = new ByteBlock(1024 * 64))
|
||||
{
|
||||
this.Save(byteBlock);
|
||||
// 将字节块的内容写入到指定的流中
|
||||
stream.Write(byteBlock.Span);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Unpackage<TByteBlock>(ref TByteBlock byteBlock)
|
||||
{
|
||||
this.ResourceHandle = byteBlock.ReadInt32();
|
||||
this.FileInfo = byteBlock.ReadPackage<RemoteFileInfo>();
|
||||
}
|
||||
|
||||
private void PrivateCreate(RemoteFileInfo fileInfo, long fileSectionSize)
|
||||
{
|
||||
this.ResourceHandle = this.GetHashCode();
|
||||
this.FileSectionSize = (int)fileSectionSize;
|
||||
var sectionCount = (int)((fileInfo.Length / fileSectionSize) + 1);
|
||||
var sections = new FileSection[sectionCount];
|
||||
for (var i = 0; i < sectionCount; i++)
|
||||
{
|
||||
var fileSection = new FileSection()
|
||||
{
|
||||
Offset = i * fileSectionSize,
|
||||
Length = (int)Math.Min(fileInfo.Length - i * fileSectionSize, fileSectionSize),
|
||||
ResourceHandle = this.ResourceHandle,
|
||||
Status = FileSectionStatus.Default,
|
||||
Index = i
|
||||
};
|
||||
sections[i] = fileSection;
|
||||
}
|
||||
this.FileInfo = fileInfo;
|
||||
this.m_fileSections = sections;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ namespace TouchSocket.Dmtp.FileTransfer;
|
||||
/// </summary>
|
||||
public class FileSectionResult : ResultBase, IDisposable
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数:初始化FileSectionResult对象,用于处理文件段结果。
|
||||
/// </summary>
|
||||
@@ -61,7 +60,8 @@ public class FileSectionResult : ResultBase, IDisposable
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
// 释放当前对象持有的资源
|
||||
this.Value.Dispose();
|
||||
var value = this.Value;
|
||||
this.Value = null;
|
||||
value.SafeDispose();
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,6 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using TouchSocket.Core;
|
||||
using static System.Collections.Specialized.BitVector32;
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
#endif
|
||||
|
||||
namespace TouchSocket.Rpc;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TouchSocket.Core;
|
||||
@@ -22,89 +23,22 @@ namespace TouchSocket.Sockets;
|
||||
/// <summary>
|
||||
/// 客户端工厂的基类,用于创建特定类型的客户端对象。
|
||||
/// </summary>
|
||||
/// <typeparam name="TClient">客户端类型,必须实现IClient接口。</typeparam>
|
||||
/// <typeparam name="TClient">客户端类型,必须实现<see cref="IClient"/>接口。</typeparam>
|
||||
public abstract class ClientFactory<TClient> : DependencyObject where TClient : IClient
|
||||
{
|
||||
private readonly ConcurrentList<TClient> m_createdClients = new ConcurrentList<TClient>();
|
||||
private readonly CancellationTokenSource m_cts = new CancellationTokenSource();
|
||||
private readonly ConcurrentQueue<TClient> m_freeClients = new ConcurrentQueue<TClient>();
|
||||
private readonly SingleTimer m_singleTimer;
|
||||
|
||||
/// <summary>
|
||||
/// 客户端工厂类的构造函数。
|
||||
/// </summary>
|
||||
public ClientFactory()
|
||||
{
|
||||
// 初始化一个单例计时器,每1000毫秒执行一次指定的回调方法。
|
||||
this.m_singleTimer = new SingleTimer(1000, () =>
|
||||
{
|
||||
// 创建一个临时客户端列表,用于存储需要移除的客户端。
|
||||
var list = new List<TClient>();
|
||||
|
||||
// 移除所有不再活跃的客户端。
|
||||
this.m_createdClients.RemoveAll(a =>
|
||||
{
|
||||
// 如果客户端不再活跃,则移除并处理该客户端。
|
||||
if (!this.IsAlive(a))
|
||||
{
|
||||
this.DisposeClient(a);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// 注释掉的代码块,用于在客户端数量不足最小值时新增客户端。
|
||||
//if (this.CreatedClients.Count < this.MinCount)
|
||||
//{
|
||||
// using (this.GetClient())
|
||||
// {
|
||||
// }
|
||||
//}
|
||||
});
|
||||
// 启动定时任务但不阻塞构造函数
|
||||
_ = this.RunPeriodicAsync();
|
||||
}
|
||||
|
||||
#region 属性
|
||||
|
||||
/// <summary>
|
||||
/// 获取可用的客户端数量。
|
||||
/// <para>
|
||||
/// 该值指示了当前空闲的客户端数量和未创建的客户端数量。
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int AvailableCount => Math.Max(0, this.MaxCount - this.CreatedClients.Count) + this.FreeClients.Count;
|
||||
|
||||
/// <summary>
|
||||
/// 获取已经创建的客户端数量。
|
||||
/// </summary>
|
||||
public int CreatedCount => this.CreatedClients.Count;
|
||||
|
||||
/// <summary>
|
||||
/// 获取空闲的客户端数量。
|
||||
/// </summary>
|
||||
public int FreeCount => this.FreeClients.Count;
|
||||
|
||||
/// <summary>
|
||||
/// 最大客户端数量。默认10。
|
||||
/// </summary>
|
||||
public int MaxCount { get; set; } = 10;
|
||||
|
||||
/// <summary>
|
||||
/// 池中维护的最小客户端数量。默认0。
|
||||
/// </summary>
|
||||
public int MinCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 已创建的客户端安全列表,一般不要直接操作。
|
||||
/// </summary>
|
||||
protected IReadOnlyList<TClient> CreatedClients => this.m_createdClients;
|
||||
|
||||
/// <summary>
|
||||
/// 空闲客户端的安全队列,一般不要直接操作。
|
||||
/// </summary>
|
||||
protected ConcurrentQueue<TClient> FreeClients => this.m_freeClients;
|
||||
|
||||
#endregion 属性
|
||||
|
||||
/// <summary>
|
||||
/// 清理池中的所有客户端。
|
||||
/// </summary>
|
||||
@@ -140,31 +74,6 @@ public abstract class ClientFactory<TClient> : DependencyObject where TClient :
|
||||
this.m_createdClients.Remove(client);
|
||||
}
|
||||
|
||||
#region GetClient
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于传输的客户端结果。可以支持<see cref="IDisposable"/>。
|
||||
/// </summary>
|
||||
/// <param name="waitTime">等待时间,超过此时间则取消获取客户端的操作。</param>
|
||||
/// <returns>返回一个<see cref="ClientFactoryResult{TClient}"/>对象,包含租用的客户端和归还客户端的方法。</returns>
|
||||
public virtual async ValueTask<ClientFactoryResult<TClient>> GetClient(TimeSpan waitTime)
|
||||
{
|
||||
// 租用客户端,并配置不等待主线程
|
||||
return new ClientFactoryResult<TClient>(await this.RentClient(waitTime).ConfigureAwait(EasyTask.ContinueOnCapturedContext), this.ReturnClient);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个指定客户端,默认情况下等待1秒。
|
||||
/// </summary>
|
||||
/// <returns>返回一个<see cref="ClientFactoryResult{TClient}"/>对象,包含租用的客户端和归还客户端的方法。</returns>
|
||||
public ValueTask<ClientFactoryResult<TClient>> GetClient()
|
||||
{
|
||||
// 使用默认等待时间1秒来获取客户端
|
||||
return this.GetClient(TimeSpan.FromSeconds(1));
|
||||
}
|
||||
|
||||
#endregion GetClient
|
||||
|
||||
/// <summary>
|
||||
/// 判断客户端是不是存活状态。
|
||||
/// </summary>
|
||||
@@ -183,7 +92,7 @@ public abstract class ClientFactory<TClient> : DependencyObject where TClient :
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
this.m_singleTimer.SafeDispose();
|
||||
this.m_cts.Cancel();
|
||||
this.Clear();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
@@ -248,6 +157,119 @@ public abstract class ClientFactory<TClient> : DependencyObject where TClient :
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExecuteAsyncTask()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 移除所有不再活跃的客户端。
|
||||
this.m_createdClients.RemoveAll(a =>
|
||||
{
|
||||
// 如果客户端不再活跃,则移除并处理该客户端。
|
||||
if (!this.IsAlive(a))
|
||||
{
|
||||
this.DisposeClient(a);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
var clients = new List<TClient>();
|
||||
while (this.CreatedCount < this.MinCount)
|
||||
{
|
||||
var client = await this.RentClient(TimeSpan.FromSeconds(1)).ConfigureAwait(EasyTask.ContinueOnCapturedContext);
|
||||
|
||||
clients.Add(client);
|
||||
}
|
||||
|
||||
foreach (var item in clients)
|
||||
{
|
||||
this.ReturnClient(item);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RunPeriodicAsync()
|
||||
{
|
||||
while (!this.m_cts.IsCancellationRequested)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(EasyTask.ContinueOnCapturedContext); // 每秒执行
|
||||
await this.ExecuteAsyncTask().ConfigureAwait(EasyTask.ContinueOnCapturedContext);
|
||||
}
|
||||
}
|
||||
|
||||
#region 属性
|
||||
|
||||
/// <summary>
|
||||
/// 获取可用的客户端数量。
|
||||
/// <para>
|
||||
/// 该值指示了当前空闲的客户端数量和未创建的客户端数量。
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int AvailableCount => Math.Max(0, this.MaxCount - this.CreatedClients.Count) + this.FreeClients.Count;
|
||||
|
||||
/// <summary>
|
||||
/// 获取已经创建的客户端数量。
|
||||
/// </summary>
|
||||
public int CreatedCount => this.CreatedClients.Count;
|
||||
|
||||
/// <summary>
|
||||
/// 获取空闲的客户端数量。
|
||||
/// </summary>
|
||||
public int FreeCount => this.FreeClients.Count;
|
||||
|
||||
/// <summary>
|
||||
/// 最大客户端数量。默认10。
|
||||
/// </summary>
|
||||
public int MaxCount { get; set; } = 10;
|
||||
|
||||
/// <summary>
|
||||
/// 池中维护的最小客户端数量。默认0。
|
||||
/// </summary>
|
||||
public int MinCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 已创建的客户端安全列表,一般不要直接操作。
|
||||
/// </summary>
|
||||
protected IReadOnlyList<TClient> CreatedClients => this.m_createdClients;
|
||||
|
||||
/// <summary>
|
||||
/// 空闲客户端的安全队列,一般不要直接操作。
|
||||
/// </summary>
|
||||
protected ConcurrentQueue<TClient> FreeClients => this.m_freeClients;
|
||||
|
||||
#endregion 属性
|
||||
|
||||
#region GetClient
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于传输的客户端结果。可以支持<see cref="IDisposable"/>。
|
||||
/// </summary>
|
||||
/// <param name="waitTime">等待时间,超过此时间则取消获取客户端的操作。</param>
|
||||
/// <returns>返回一个<see cref="ClientFactoryResult{TClient}"/>对象,包含租用的客户端和归还客户端的方法。</returns>
|
||||
public virtual async ValueTask<ClientFactoryResult<TClient>> GetClient(TimeSpan waitTime)
|
||||
{
|
||||
// 租用客户端,并配置不等待主线程
|
||||
return new ClientFactoryResult<TClient>(await this.RentClient(waitTime).ConfigureAwait(EasyTask.ContinueOnCapturedContext), this.ReturnClient);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个指定客户端,默认情况下等待1秒。
|
||||
/// </summary>
|
||||
/// <returns>返回一个<see cref="ClientFactoryResult{TClient}"/>对象,包含租用的客户端和归还客户端的方法。</returns>
|
||||
public ValueTask<ClientFactoryResult<TClient>> GetClient()
|
||||
{
|
||||
// 使用默认等待时间1秒来获取客户端
|
||||
return this.GetClient(TimeSpan.FromSeconds(1));
|
||||
}
|
||||
|
||||
#endregion GetClient
|
||||
|
||||
private bool Wait()
|
||||
{
|
||||
return !this.FreeClients.IsEmpty;
|
||||
|
||||
Reference in New Issue
Block a user