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 1 commit
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
9 changes: 4 additions & 5 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 @@ -125,10 +125,9 @@ public void Dispose()

private bool _isDisposed;

private readonly object _locker = new object();
private readonly object _locker = new();
Copy link
Member

Choose a reason for hiding this comment

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

由于采用源代码形式分发,考虑到源代码兼容性,不打算采用此语法特性


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

/// <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
12 changes: 6 additions & 6 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 Expand Up @@ -221,8 +222,7 @@ public async ValueTask WaitForCurrentFinished()
await _currentFinishedTaskCompletionSource.Task.ConfigureAwait(false);
}

private readonly TaskCompletionSource<bool> _currentFinishedTaskCompletionSource =
new TaskCompletionSource<bool>();
private readonly TaskCompletionSource<bool> _currentFinishedTaskCompletionSource = new();

private readonly AsyncQueue<T> _asyncQueue;

Expand Down
33 changes: 19 additions & 14 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 All @@ -182,8 +184,8 @@ private async void InternalRunning()

private bool TryGetNextTask(out AwaitableTask task)
{
task = null;
while (_queue.Count > 0)
task = default;
while (_queue.Count is 0)
Copy link
Member

@lindexi lindexi Oct 20, 2022

Choose a reason for hiding this comment

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

这个逻辑是错误的

这里是不断获取队列内容

{
//获取并从队列中移除任务
if (_queue.TryDequeue(out task) && (!AutoCancelPreviousTask || _queue.Count == 0))
Expand All @@ -199,7 +201,7 @@ private bool TryGetNextTask(out AwaitableTask task)
task.SetNotExecutable();
}

return false;
return default;
Copy link
Member

Choose a reason for hiding this comment

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

对于布尔来说,使用 false 更加表意

}

#endregion
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 @@ -271,8 +275,9 @@ public bool AutoCancelPreviousTask
private object Locker => _queue;
private bool _isDisposed;
private bool _isDisposing;
private readonly ConcurrentQueue<AwaitableTask> _queue = new ConcurrentQueue<AwaitableTask>();
private readonly ConcurrentQueue<AwaitableTask> _queue = new();
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
6 changes: 3 additions & 3 deletions 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 All @@ -30,15 +30,15 @@ class AwaitableTask
/// </summary>
public void SetNotExecutable()
{
Executable = false;
Executable = default;
Copy link
Member

Choose a reason for hiding this comment

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

对于布尔来说,使用 true 和 false 更加表意

}

/// <summary>
/// 标记任务无效
/// </summary>
public void MarkTaskInvalid()
{
IsValid = false;
IsValid = default;
}

#region Task
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
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
3 changes: 2 additions & 1 deletion 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 @@ -109,6 +109,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
12 changes: 7 additions & 5 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 @@ -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
Loading