Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

init:.Net 6版本初始化 #70

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions AsyncWorkerCollection/AsyncAutoResetEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace dotnetCampus.Threading
#else
public
#endif
class AsyncAutoResetEvent : IDisposable
class AsyncAutoResetEvent : IDisposable
{
/// <summary>
/// 提供一个信号初始值,确定是否有信号
Expand Down Expand Up @@ -72,7 +72,7 @@ public Task<bool> WaitOneAsync()
/// </summary>
public void Set()
{
TaskCompletionSource<bool>? releaseSource = null;
TaskCompletionSource<bool>? releaseSource = default;
bool result;
lock (_locker)
{
Expand Down Expand Up @@ -127,8 +127,7 @@ public void Dispose()

private readonly object _locker = new object();

private readonly Queue<TaskCompletionSource<bool>> _waitQueue =
new Queue<TaskCompletionSource<bool>>();
private readonly Queue<TaskCompletionSource<bool>> _waitQueue = new Queue<TaskCompletionSource<bool>>();

/// <summary>
/// 用于在没有任何等待时让下一次等待通过
Expand Down
2 changes: 1 addition & 1 deletion AsyncWorkerCollection/AsyncManualResetEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace dotnetCampus.Threading
#else
public
#endif
class AsyncManualResetEvent
class AsyncManualResetEvent
{
/// <summary>
/// 提供一个信号初始值,确定是否有信号
Expand Down
9 changes: 5 additions & 4 deletions AsyncWorkerCollection/AsyncQueue.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#nullable enable

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

#if !NETCOREAPP
using ValueTask = System.Threading.Tasks.Task;
#endif
Expand All @@ -20,7 +20,7 @@ namespace dotnetCampus.Threading
#else
public
#endif
class AsyncQueue<T> : IDisposable, IAsyncDisposable
class AsyncQueue<T> : IDisposable, IAsyncDisposable
{
private readonly SemaphoreSlim _semaphoreSlim;
private readonly ConcurrentQueue<T> _queue;
Expand Down Expand Up @@ -119,7 +119,7 @@ public async Task<T> DequeueAsync(CancellationToken cancellationToken = default)
/// <returns></returns>
public async ValueTask WaitForCurrentFinished()
{
if (_queue.Count == 0)
if (_queue.Count is 0)
{
return;
}
Expand All @@ -128,7 +128,7 @@ public async ValueTask WaitForCurrentFinished()

// 有线程执行事件触发,刚好此时在创建 CurrentFinishedTask 对象
// 此时需要重新判断是否存在任务
if (_queue.Count == 0)
if (_queue.Count is 0)
{
return;
}
Expand All @@ -155,6 +155,7 @@ public void Dispose()
// 释放 DequeueAsync 方法,释放次数为 DequeueAsync 在调用的次数
_semaphoreSlim.Release(_dequeueAsyncEnterCount);
}

_semaphoreSlim.Dispose();
}

Expand Down
25 changes: 15 additions & 10 deletions AsyncWorkerCollection/AsyncTaskQueue_/AsyncTaskQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace dotnetCampus.Threading
#else
public
#endif
class AsyncTaskQueue : IDisposable
class AsyncTaskQueue : IDisposable
{
/// <summary>
/// 异步任务队列
Expand Down Expand Up @@ -160,16 +160,18 @@ private async void InternalRunning()
//如已从队列中删除
if (!task.Executable) continue;
//添加是否已释放的判断
if (!_isDisposing)
if (_isDisposing)
{
if (UseSingleThread)
{
task.RunSynchronously();
}
else
{
task.Start();
}
continue;
}

if (UseSingleThread)
{
task.RunSynchronously();
}
else
{
task.Start();
}
}
}
Expand Down Expand Up @@ -228,7 +230,9 @@ private void Dispose(bool disposing)
lock (Locker)
{
if (_isDisposed) return;

_isDisposing = true;

if (disposing)
{
}
Expand Down Expand Up @@ -273,6 +277,7 @@ public bool AutoCancelPreviousTask
private bool _isDisposing;
private readonly ConcurrentQueue<AwaitableTask> _queue = new ConcurrentQueue<AwaitableTask>();
private readonly AsyncAutoResetEvent _autoResetEvent;

// ReSharper disable once RedundantDefaultMemberInitializer
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

请问,这个地方的初始化语法镇压有什么特殊含义么?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Komi-Thaw 只是让 Resharper 开心而已

这里明确给定 _autoCancelPreviousTask 的初始值为 false 的值,和默认 bool 行为相同,此时 Resharper 没有理解意图,毕竟执行逻辑是等价的,于是提示这个 false 可以删除。但是这里我期望是明确给定 false 初始值,以便在后续有期望更改为 true 的时候,可以看到,之前的设计就是明确要 false 值

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好的

private bool _autoCancelPreviousTask = false;

Expand Down
2 changes: 1 addition & 1 deletion AsyncWorkerCollection/AsyncTaskQueue_/AwaitableTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace dotnetCampus.Threading
#else
public
#endif
class AwaitableTask
class AwaitableTask
{
/// <summary>
/// 获取任务是否为不可执行状态
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace dotnetCampus.Threading
#else
public
#endif
class AwaitableTask<TResult> : AwaitableTask
class AwaitableTask<TResult> : AwaitableTask
{
/// <summary>
/// 初始化可等待的任务
Expand Down
1 change: 1 addition & 0 deletions AsyncWorkerCollection/AsyncWorkerCollection.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>dotnetCampus.AsyncWorkerCollection</AssemblyName>
<LangVersion>8</LangVersion>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个是不加的,因为将会作为源代码包分发

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好的 我这边主要是为了使用Rider方便些加上去的

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KomiSans 好奇怪,居然你不用VS开发

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rider更智能一些其实

</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)'!='net45' AND '$(TargetFramework)'!='netstandard2.0'">
Expand Down
8 changes: 1 addition & 7 deletions AsyncWorkerCollection/ConcurrentQueueExtension.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;

namespace dotnetCampus.Threading
{
Expand All @@ -14,7 +9,6 @@ public static void Clear<T>(this ConcurrentQueue<T> queue)
{
while (queue.TryDequeue(out _))
{

}
}
}
Expand Down
15 changes: 4 additions & 11 deletions AsyncWorkerCollection/DoubleBuffer_/DoubleBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace dotnetCampus.Threading
#else
public
#endif
class DoubleBuffer<T, TU> where T : class, ICollection<TU>
class DoubleBuffer<T, TU> where T : class, ICollection<TU>
{
/// <summary>
/// 创建双缓存
Expand Down Expand Up @@ -50,16 +50,8 @@ public T SwitchBuffer()
{
lock (_lock)
{
if (ReferenceEquals(CurrentList, AList))
{
CurrentList = BList;
return AList;
}
else
{
CurrentList = AList;
return BList;
}
CurrentList = ReferenceEquals(CurrentList, AList) ? AList : BList;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的逻辑需要两次判断,不如原先的

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好的,我去改过来

return ReferenceEquals(CurrentList, AList) ? BList : AList;
}
}

Expand Down Expand Up @@ -109,6 +101,7 @@ internal bool GetIsEmpty()
/// 用于给其他类型的同步使用的对象
/// </summary>
internal object SyncObject => _lock;

private readonly object _lock = new object();

private T CurrentList { set; get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace dotnetCampus.Threading
#else
public
#endif
class DoubleBufferLazyInitializeTask<T>
class DoubleBufferLazyInitializeTask<T>
{
/// <summary>
/// 初始化可等待初始化之后才执行实际任务的双缓存工具
Expand Down Expand Up @@ -48,16 +48,9 @@ public void OnInitialized()

lock (Locker)
{
if (_waitForInitializationTask != null)
{
// 如果不是空
// 那么设置任务完成
_waitForInitializationTask.SetResult(true);
}
else
{
// 如果是空,那么 DoInner 还没进入,此时啥都不需要做
}
// 如果不是空
// 那么设置任务完成
_waitForInitializationTask?.SetResult(true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

原本的写法是表示空和非空都在处理逻辑内,而且也方便加上断点进行调试。这个逻辑不做简化

}
}

Expand Down Expand Up @@ -91,15 +84,15 @@ public void AddTask(T data)

private async Task DoInner(List<T> dataList)
{
// 根据 DoubleBufferTask 的设计,这个方法只有一个线程进入
FirstCheckInitialized: // 标签:第一个判断初始化方法
// 根据 DoubleBufferTask 的设计,这个方法只有一个线程进入
FirstCheckInitialized: // 标签:第一个判断初始化方法
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里用到部分 Goto 的方式,似乎对标签的缩进格式有所不同。我比较喜欢使用不缩进的方式,用来表示标签就是和其他代码不同

if (!_isInitialized)
{
// 还没有初始化,等待一下
// 如果此时还没有任务可以等待,那么创建一下任务
lock (Locker)
{
SecondCheckInitialized: // 标签:第二个判断初始化方法
SecondCheckInitialized: // 标签:第二个判断初始化方法
if (!_isInitialized)
{
// 此时的值一定是空
Expand All @@ -112,21 +105,19 @@ private async Task DoInner(List<T> dataList)
{
await _waitForInitializationTask!.Task.ConfigureAwait(false);
}
else
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个空 else 是用来表示另一个情况的,不简化哦

{
// 此时初始化方法被调用,因此不需要再调用等待
// 如果先进入 FirstCheckInitialized 标签的第一个判断初始化方法,此时 OnInitialized 没有被调用
// 因此进入分支
// 如果刚好此时 OnInitialized 方法进入,同时设置了 _isInitialized 是 true 值
// 如果此时的 OnInitialized 方法比 DoInner 先获得锁,那么将判断 _waitForInitializationTask 是空,啥都不做
// 然后 DoInner 在等待 OnInitialized 的 Locker 锁,进入锁之后,先通过 SecondCheckInitialized 标签的第二个判断初始化方法
// 这个判断是线程安全的,因此如果是 OnInitialized 已进入同时获取锁,那么此时在等待 Locker 锁之后一定拿到新的值
// 如果是 DoInner 先获得锁,那么此时也许 _isInitialized 不靠谱,但其实不依赖 _isInitialized 靠谱,因此 _isInitialized 只有一个状态,就是从 false 到 true 的值
// 此时如果判断 _isInitialized 是 true 的值,也就不需要再创建一个任务用来等待了
// 也就会最终进入此分支
}

// 此时初始化方法被调用,因此不需要再调用等待
// 如果先进入 FirstCheckInitialized 标签的第一个判断初始化方法,此时 OnInitialized 没有被调用
// 因此进入分支
// 如果刚好此时 OnInitialized 方法进入,同时设置了 _isInitialized 是 true 值
// 如果此时的 OnInitialized 方法比 DoInner 先获得锁,那么将判断 _waitForInitializationTask 是空,啥都不做
// 然后 DoInner 在等待 OnInitialized 的 Locker 锁,进入锁之后,先通过 SecondCheckInitialized 标签的第二个判断初始化方法
// 这个判断是线程安全的,因此如果是 OnInitialized 已进入同时获取锁,那么此时在等待 Locker 锁之后一定拿到新的值
// 如果是 DoInner 先获得锁,那么此时也许 _isInitialized 不靠谱,但其实不依赖 _isInitialized 靠谱,因此 _isInitialized 只有一个状态,就是从 false 到 true 的值
// 此时如果判断 _isInitialized 是 true 的值,也就不需要再创建一个任务用来等待了
// 也就会最终进入此分支
// 只需要等待一次,然后可以释放内存

_waitForInitializationTask = null;
}

Expand Down
14 changes: 8 additions & 6 deletions AsyncWorkerCollection/DoubleBuffer_/DoubleBufferTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace dotnetCampus.Threading
#else
public
#endif
class DoubleBufferTask<T, TU> : IAsyncDisposable
class DoubleBufferTask<T, TU> : IAsyncDisposable
where T : class, ICollection<TU>
{
/// <summary>
Expand Down Expand Up @@ -50,7 +50,7 @@ public void AddTask(TU t)
if (isSetFinish == 1)
{
// 被设置完成了,业务上就不应该再次给任何的数据内容
throw new InvalidOperationException($"The DoubleBufferTask has been set finish.");
throw new InvalidOperationException("The DoubleBufferTask has been set finish.");
}

DoubleBuffer.Add(t);
Expand All @@ -74,12 +74,14 @@ private async void DoInner()

lock (Locker)
{
if (DoubleBuffer.GetIsEmpty())
if (!DoubleBuffer.GetIsEmpty())
{
_isDoing = false;
Finished?.Invoke(this, EventArgs.Empty);
break;
continue;
}

_isDoing = false;
Finished?.Invoke(this, EventArgs.Empty);
break;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion AsyncWorkerCollection/DoubleBuffer_/DoubleBufferTask`T.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace dotnetCampus.Threading
#else
public
#endif
class DoubleBufferTask<T> : DoubleBufferTask<List<T>, T>
class DoubleBufferTask<T> : DoubleBufferTask<List<T>, T>
{
/// <summary>
/// 创建双缓存任务,执行任务的方法放在 <paramref name="doTask"/> 方法
Expand Down
2 changes: 1 addition & 1 deletion AsyncWorkerCollection/DoubleBuffer_/DoubleBuffer`T.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace dotnetCampus.Threading
#else
public
#endif
class DoubleBuffer<T> : DoubleBuffer<List<T>, T>
class DoubleBuffer<T> : DoubleBuffer<List<T>, T>
{
/// <summary>
/// 创建使用 <see cref="List&lt;T&gt;"/> 的双缓存
Expand Down
5 changes: 3 additions & 2 deletions AsyncWorkerCollection/ExecuteOnceAwaiter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace dotnetCampus.Threading
#else
public
#endif
class ExecuteOnceAwaiter<TResult>
class ExecuteOnceAwaiter<TResult>
{
/// <summary>
/// 创建只执行一次的等待,调用 <see cref="ExecuteAsync"/> 时,无论调用多少次,只会执行 <paramref name="asyncAction"/> 一次
Expand Down Expand Up @@ -53,14 +53,15 @@ public void ResetWhileCompleted()
{
if (_executionResult?.IsCompleted is true)
{
_executionResult = null;
_executionResult = default;
}
}
}

private readonly object _locker = new object();

private readonly Func<Task<TResult>> _asyncAction;

private Task<TResult> _executionResult;
}
}
Loading