Skip to content

Commit e66884b

Browse files
authored
Merge pull request #19 from dotnet-campus/t/lindexi/FerbeecelferrelawCeefeljalwedem
修复线程安全
2 parents 599297b + e35bcc5 commit e66884b

File tree

1 file changed

+31
-27
lines changed

1 file changed

+31
-27
lines changed

AsyncWorkerCollection/ExecuteOnceAwaiter.cs

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,54 +4,58 @@
44

55
namespace dotnetCampus.Threading
66
{
7+
/// <summary>
8+
/// 只执行一次的等待
9+
/// </summary>
10+
/// <typeparam name="TResult"></typeparam>
711
public class ExecuteOnceAwaiter<TResult>
812
{
13+
/// <summary>
14+
/// 创建只执行一次的等待,调用 <see cref="ExecuteAsync"/> 时,无论调用多少次,只会执行 <paramref name="asyncAction"/> 一次
15+
/// <para></para>
16+
/// 因为此类使用了锁,因此需要调用方处理 <paramref name="asyncAction"/> 自身线程安全问题
17+
/// </summary>
18+
/// <param name="asyncAction">执行的具体逻辑,需要调用方处理自身线程安全问题</param>
919
public ExecuteOnceAwaiter(Func<Task<TResult>> asyncAction)
1020
{
1121
_asyncAction = asyncAction;
1222
}
1323

24+
/// <summary>
25+
/// 执行传入的具体逻辑,无论多少线程多少次调用,传入的具体逻辑只会执行一次
26+
/// </summary>
27+
/// <returns></returns>
1428
public Task<TResult> ExecuteAsync()
1529
{
16-
if (_executionResult != null)
30+
lock (_locker)
1731
{
32+
if (_executionResult != null)
33+
{
34+
return _executionResult;
35+
}
36+
37+
_executionResult = _asyncAction();
1838
return _executionResult;
1939
}
20-
21-
Lock(() => _executionResult = _asyncAction());
22-
23-
return _executionResult;
2440
}
2541

42+
/// <summary>
43+
/// 在传入的具体逻辑执行完成之后,设置允许重新执行。如果此具体逻辑还在执行中,那么此方法调用无效
44+
/// </summary>
2645
public void ResetWhileCompleted()
2746
{
28-
if (IsCompleted)
47+
lock (_locker)
2948
{
30-
Lock(() => _executionResult = null);
49+
if (_executionResult?.IsCompleted is true)
50+
{
51+
_executionResult = null;
52+
}
3153
}
3254
}
3355

56+
private readonly object _locker = new object();
57+
3458
private readonly Func<Task<TResult>> _asyncAction;
3559
private Task<TResult> _executionResult;
36-
private SpinLock _spinLock = new SpinLock(true);
37-
38-
private bool IsRunning => _executionResult?.IsCompleted is false;
39-
40-
private bool IsCompleted => _executionResult?.IsCompleted is true;
41-
42-
private void Lock(Action action)
43-
{
44-
var lockTaken = false;
45-
try
46-
{
47-
_spinLock.Enter(ref lockTaken);
48-
action();
49-
}
50-
finally
51-
{
52-
// 参数错误或锁递归时才会发生异常,所以此处几乎能肯定 lockTaken 为 true。
53-
if (lockTaken) _spinLock.Exit();
54-
}
55-
}
5660
}
5761
}

0 commit comments

Comments
 (0)