7
7
using Avalonia . Controls ;
8
8
using Avalonia . Media . Imaging ;
9
9
using System . Collections . Concurrent ;
10
+ using Avalonia . Logging ;
10
11
11
12
namespace AsyncImageLoader ;
12
13
13
14
public static class ImageLoader
14
15
{
15
- public const string AsyncImageLoaderLogArea = "AsyncImageLoader" ;
16
+ private static readonly ParametrizedLogger ? Logger ;
17
+ public const string AsyncImageLoaderLogArea = "AsyncImageLoader" ;
16
18
17
19
public static readonly AttachedProperty < string ? > SourceProperty =
18
20
AvaloniaProperty . RegisterAttached < Image , string ? > ( "Source" , typeof ( ImageLoader ) ) ;
@@ -23,16 +25,17 @@ public static class ImageLoader
23
25
static ImageLoader ( )
24
26
{
25
27
SourceProperty . Changed . AddClassHandler < Image > ( OnSourceChanged ) ;
28
+ Logger = Avalonia . Logging . Logger . TryGet ( LogEventLevel . Error , AsyncImageLoaderLogArea ) ;
26
29
}
27
30
28
31
public static IAsyncImageLoader AsyncImageLoader { get ; set ; } = new RamCachedWebImageLoader ( ) ;
29
32
30
- private static ConcurrentDictionary < Image , CancellationTokenSource > _pendingOperations = new ConcurrentDictionary < Image , CancellationTokenSource > ( ) ;
33
+ private static readonly ConcurrentDictionary < Image , CancellationTokenSource > PendingOperations = new ( ) ;
31
34
private static async void OnSourceChanged ( Image sender , AvaloniaPropertyChangedEventArgs args ) {
32
35
var url = args . GetNewValue < string ? > ( ) ;
33
36
34
37
// Cancel/Add new pending operation
35
- CancellationTokenSource ? cts = _pendingOperations . AddOrUpdate ( sender , new CancellationTokenSource ( ) ,
38
+ CancellationTokenSource ? cts = PendingOperations . AddOrUpdate ( sender , new CancellationTokenSource ( ) ,
36
39
( x , y ) =>
37
40
{
38
41
y . Cancel ( ) ;
@@ -41,7 +44,7 @@ private static async void OnSourceChanged(Image sender, AvaloniaPropertyChangedE
41
44
42
45
if ( url == null )
43
46
{
44
- ( ( ICollection < KeyValuePair < Image , CancellationTokenSource > > ) _pendingOperations ) . Remove ( new KeyValuePair < Image , CancellationTokenSource > ( sender , cts ) ) ;
47
+ ( ( ICollection < KeyValuePair < Image , CancellationTokenSource > > ) PendingOperations ) . Remove ( new KeyValuePair < Image , CancellationTokenSource > ( sender , cts ) ) ;
45
48
sender . Source = null ;
46
49
return ;
47
50
}
@@ -62,13 +65,19 @@ private static async void OnSourceChanged(Image sender, AvaloniaPropertyChangedE
62
65
{
63
66
return null ;
64
67
}
68
+ catch ( Exception e )
69
+ {
70
+ Logger ? . Log ( LogEventLevel . Error , "ImageLoader image resolution failed: {0}" , e ) ;
71
+
72
+ return null ;
73
+ }
65
74
} ) ;
66
75
67
76
if ( bitmap != null && ! cts . Token . IsCancellationRequested )
68
77
sender . Source = bitmap ! ;
69
78
70
79
// "It is not guaranteed to be thread safe by ICollection, but ConcurrentDictionary's implementation is. Additionally, we recently exposed this API for .NET 5 as a public ConcurrentDictionary.TryRemove"
71
- ( ( ICollection < KeyValuePair < Image , CancellationTokenSource > > ) _pendingOperations ) . Remove ( new KeyValuePair < Image , CancellationTokenSource > ( sender , cts ) ) ;
80
+ ( ( ICollection < KeyValuePair < Image , CancellationTokenSource > > ) PendingOperations ) . Remove ( new KeyValuePair < Image , CancellationTokenSource > ( sender , cts ) ) ;
72
81
SetIsLoading ( sender , false ) ;
73
82
}
74
83
0 commit comments