@@ -30,13 +30,6 @@ namespace SmartImage.Searching
3030 /// </summary>
3131 public sealed class SearchClient
3232 {
33- /*
34- * todo: use async/tasks
35- * todo: timeout handling
36- */
37-
38- private const string ORIGINAL_IMAGE_NAME = "(Original image)" ;
39-
4033 private static readonly string InterfacePrompt =
4134 $ "Enter the option number to open or { NConsole . NC_GLOBAL_EXIT_KEY } to exit.\n " +
4235 $ "Hold down { NC_ALT_FUNC_MODIFIER } to show more info.\n " +
@@ -58,17 +51,13 @@ public sealed class SearchClient
5851 /// </summary>
5952 private string ImageUrl { get ; }
6053
61- /// <summary>
62- /// Thread that monitors the search (<see cref="RunSearchMonitor"/>)
63- /// </summary>
64- private Thread SearchMonitor { get ; }
6554
6655 /// <summary>
6756 /// Search tasks (<seealso cref="CreateSearchTasks"/>)
6857 /// </summary>
69- private Task [ ] SearchTasks { get ; }
58+ private List < Task < FullSearchResult > > SearchTasks { get ; }
59+
7060
71-
7261 /// <summary>
7362 /// Whether the search is complete
7463 /// </summary>
@@ -115,15 +104,6 @@ private SearchClient(string img)
115104
116105 SearchTasks = CreateSearchTasks ( ) ;
117106
118- // Joining each thread isn't necessary as this object is disposed upon program exit
119- // Background threads won't prevent program termination
120-
121- SearchMonitor = new Thread ( RunSearchMonitor )
122- {
123- Priority = ThreadPriority . Highest ,
124- IsBackground = true
125- } ;
126-
127107 Complete = false ;
128108
129109 Interface = new NConsoleInterface ( Results )
@@ -133,16 +113,34 @@ private SearchClient(string img)
133113 } ;
134114 }
135115
116+
136117 /// <summary>
137- /// Monitors the search process
118+ /// Starts search and handles results
138119 /// </summary>
139- private void RunSearchMonitor ( )
120+ public async void Start ( )
140121 {
141- while ( SearchTasks . Any ( t => ! t . IsCompleted ) ) {
142- int inProgress = SearchTasks . Count ( t => t . IsCompleted ) ;
143- int len = SearchTasks . Length ;
122+ int len = SearchTasks . Count ;
123+
124+ while ( SearchTasks . Any ( ) ) {
125+ Task < FullSearchResult > finished = await Task . WhenAny ( SearchTasks ) ;
126+ SearchTasks . Remove ( finished ) ;
127+
128+ var result = finished . Result ;
129+
130+ Results . Add ( result ) ;
131+ Results . Sort ( FullSearchResult . CompareResults ) ;
132+
133+ // If the engine is priority, open its result in the browser
134+ if ( result . IsPriority ) {
135+ HandleResultOpen ( result ) ;
136+ }
137+
138+ int inProgress = len - SearchTasks . Count ;
144139
145140 Interface . Status = $ "Searching: { inProgress } /{ len } ";
141+
142+ // Reload console UI
143+ NConsole . Refresh ( ) ;
146144 }
147145
148146 /*
@@ -177,76 +175,17 @@ private void RunSearchMonitor()
177175 }
178176 }
179177
180- /// <summary>
181- /// Starts search
182- /// </summary>
183- public void Start ( )
184- {
185- SearchMonitor . Start ( ) ;
186-
187- foreach ( var task in SearchTasks ) {
188- task . Start ( ) ;
189- }
190- }
191-
192- /// <summary>
193- /// Creates a <see cref="FullSearchResult"/> for the original image
194- /// </summary>
195- private FullSearchResult GetOriginalImageResult ( )
196- {
197- var result = new FullSearchResult ( Color . White , ORIGINAL_IMAGE_NAME , ImageUrl )
198- {
199- Similarity = 100.0f ,
200- } ;
201-
202- var fileFormat = FileSystem . ResolveFileType ( ImageFile . FullName ) ;
203-
204- double fileSizeMegabytes =
205- MathHelper . ConvertToUnit ( FileSystem . GetFileSize ( ImageFile . FullName ) , MetricUnit . Mega ) ;
206-
207- ( int width , int height ) = Images . GetDimensions ( ImageFile . FullName ) ;
208178
209- result . Width = width ;
210- result . Height = height ;
211-
212- double mpx = MathHelper . ConvertToUnit ( width * height , MetricUnit . Mega ) ;
213-
214- string infoStr = $ "Info: { ImageFile . Name } ({ fileSizeMegabytes : F} MB) ({ mpx : F} MP) ({ fileFormat . Name } )";
215-
216- result . ExtendedInfo . Add ( infoStr ) ;
217-
218- return result ;
219- }
220-
221- private Task [ ] CreateSearchTasks ( )
179+ private List < Task < FullSearchResult > > CreateSearchTasks ( )
222180 {
223- // todo: improve, hacky :(
224-
225181 var availableEngines = GetAllEngines ( )
226182 . Where ( e => Engines . HasFlag ( e . Engine ) )
227183 . ToArray ( ) ;
228184
229-
230- Results . Add ( GetOriginalImageResult ( ) ) ;
185+ // Add original image to results
186+ Results . Add ( FullSearchResult . GetOriginalImageResult ( ImageUrl , ImageFile ) ) ;
231187
232-
233- return availableEngines . Select ( currentEngine => new Task ( ( ) =>
234- {
235- var result = currentEngine . GetResult ( ImageUrl ) ;
236-
237- Results . Add ( result ) ;
238-
239- // If the engine is priority, open its result in the browser
240- if ( SearchConfig . Config . PriorityEngines . HasFlag ( currentEngine . Engine ) ) {
241- HandleResultOpen ( result ) ;
242- }
243-
244- // Sort results
245- Results . Sort ( FullSearchResult . CompareResults ) ;
246-
247- // Reload console UI
248- NConsole . Refresh ( ) ;
249- } ) ) . ToArray ( ) ;
188+ return availableEngines . Select ( currentEngine => Task . Run ( ( ) => currentEngine . GetResult ( ImageUrl ) ) ) . ToList ( ) ;
250189 }
251190
252191 /// <summary>
@@ -276,8 +215,6 @@ private static void HandleResultOpen(FullSearchResult result)
276215 else {
277216 Debug . WriteLine ( $ "Filtering result { result . Name } ") ;
278217 }
279-
280-
281218 }
282219
283220
0 commit comments