Skip to content
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
Copy Markdown
Author

Choose a reason for hiding this comment

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

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

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
Member

Choose a reason for hiding this comment

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

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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
Member

Choose a reason for hiding this comment

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

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

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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