1
1
using System ;
2
2
using System . ComponentModel ;
3
+ using System . Threading ;
4
+ using System . Threading . Tasks ;
3
5
using Xamarin . CommunityToolkit . Helpers ;
4
6
using Xamarin . Forms ;
5
7
@@ -12,9 +14,10 @@ namespace Xamarin.CommunityToolkit.ObjectModel.Internals
12
14
public abstract partial class BaseCommand < TCanExecute >
13
15
{
14
16
readonly Func < TCanExecute ? , bool > canExecute ;
17
+ readonly SemaphoreSlim semaphoreSlim = new SemaphoreSlim ( 1 , 1 ) ;
15
18
readonly DelegateWeakEventManager weakEventManager = new DelegateWeakEventManager ( ) ;
16
19
17
- volatile int executionCount ;
20
+ int executionCount ;
18
21
19
22
/// <summary>
20
23
/// Initializes BaseCommand
@@ -51,18 +54,11 @@ protected int ExecutionCount
51
54
get => executionCount ;
52
55
set
53
56
{
54
- var shouldRaiseCanExecuteChanged = ( AllowsMultipleExecutions , executionCount , value ) switch
55
- {
56
- ( true , _ , _ ) => false ,
57
- ( false , 0 , > 0 ) => true ,
58
- ( false , > 0 , 0 ) => true ,
59
- ( false , _ , _ ) => false
60
- } ;
57
+ var previousExecutionCount = executionCount ;
61
58
62
59
executionCount = value ;
63
60
64
- if ( shouldRaiseCanExecuteChanged )
65
- RaiseCanExecuteChanged ( ) ;
61
+ HandleExecutionCountChanged ( previousExecutionCount , value ) . SafeFireAndForget ( ) ;
66
62
}
67
63
}
68
64
@@ -95,5 +91,28 @@ public void RaiseCanExecuteChanged()
95
91
/// </summary>
96
92
[ EditorBrowsable ( EditorBrowsableState . Never ) ]
97
93
public void ChangeCanExecute ( ) => RaiseCanExecuteChanged ( ) ;
94
+
95
+ async Task HandleExecutionCountChanged ( int updatedExecutionCount , int previousExecutionCount )
96
+ {
97
+ await semaphoreSlim . WaitAsync ( ) . ConfigureAwait ( true ) ;
98
+
99
+ try
100
+ {
101
+ var shouldRaiseCanExecuteChanged = ( AllowsMultipleExecutions , updatedExecutionCount , previousExecutionCount ) switch
102
+ {
103
+ ( true , _ , _ ) => false ,
104
+ ( false , 0 , > 0 ) => true ,
105
+ ( false , > 0 , 0 ) => true ,
106
+ ( false , _ , _ ) => false
107
+ } ;
108
+
109
+ if ( shouldRaiseCanExecuteChanged )
110
+ RaiseCanExecuteChanged ( ) ;
111
+ }
112
+ finally
113
+ {
114
+ semaphoreSlim . Release ( ) ;
115
+ }
116
+ }
98
117
}
99
118
}
0 commit comments