@@ -34,7 +34,7 @@ public partial class MainViewModel : BaseModel, ISavable, IDisposable
3434 private bool _isQueryRunning ;
3535 private Query _lastQuery ;
3636 private string _queryTextBeforeLeaveResults ;
37- private string _ignoredQueryText = null ;
37+ private string _ignoredQueryText ; // Used to ignore query text change when switching between context menu and query results
3838
3939 private readonly FlowLauncherJsonStorage < History > _historyItemsStorage ;
4040 private readonly FlowLauncherJsonStorage < UserSelectedRecord > _userSelectedRecordStorage ;
@@ -45,6 +45,7 @@ public partial class MainViewModel : BaseModel, ISavable, IDisposable
4545 private readonly TopMostRecord _topMostRecord ;
4646
4747 private CancellationTokenSource _updateSource ; // Used to cancel old query flows
48+ private CancellationToken _updateToken ; // Used to avoid ObjectDisposedException of _updateSource.Token
4849
4950 private ChannelWriter < ResultsForUpdate > _resultsUpdateChannelWriter ;
5051 private Task _resultsViewUpdateTask ;
@@ -60,6 +61,9 @@ public MainViewModel()
6061 _queryTextBeforeLeaveResults = "" ;
6162 _queryText = "" ;
6263 _lastQuery = new Query ( ) ;
64+ _ignoredQueryText = null ;
65+ _updateSource = new CancellationTokenSource ( ) ;
66+ _updateToken = _updateSource . Token ;
6367
6468 Settings = Ioc . Default . GetRequiredService < Settings > ( ) ;
6569 Settings . PropertyChanged += ( _ , args ) =>
@@ -241,7 +245,7 @@ public void RegisterResultsUpdatedEvent()
241245 return ;
242246 }
243247
244- var token = e . Token == default ? _updateSource . Token : e . Token ;
248+ var token = e . Token == default ? _updateToken : e . Token ;
245249
246250 // make a clone to avoid possible issue that plugin will also change the list and items when updating view model
247251 var resultsCopy = DeepCloneResults ( e . Results , token ) ;
@@ -1213,7 +1217,7 @@ private void QueryHistory()
12131217
12141218 private async Task QueryResultsAsync ( bool searchDelay , bool isReQuery = false , bool reSelect = true )
12151219 {
1216- _updateSource ? . Cancel ( ) ;
1220+ _updateSource . Cancel ( ) ;
12171221
12181222 App . API . LogDebug ( ClassName , $ "Start query with text: <{ QueryText } >") ;
12191223
@@ -1239,15 +1243,17 @@ private async Task QueryResultsAsync(bool searchDelay, bool isReQuery = false, b
12391243
12401244 App . API . LogDebug ( ClassName , $ "Start query with ActionKeyword <{ query . ActionKeyword } > and RawQuery <{ query . RawQuery } >") ;
12411245
1246+ _updateSource . Dispose ( ) ;
12421247 _updateSource = new CancellationTokenSource ( ) ;
1248+ _updateToken = _updateSource . Token ;
12431249
12441250 ProgressBarVisibility = Visibility . Hidden ;
12451251 _isQueryRunning = true ;
12461252
12471253 // Switch to ThreadPool thread
12481254 await TaskScheduler . Default ;
12491255
1250- if ( _updateSource . Token . IsCancellationRequested ) return ;
1256+ if ( _updateToken . IsCancellationRequested ) return ;
12511257
12521258 // Update the query's IsReQuery property to true if this is a re-query
12531259 query . IsReQuery = isReQuery ;
@@ -1280,28 +1286,27 @@ private async Task QueryResultsAsync(bool searchDelay, bool isReQuery = false, b
12801286 {
12811287 // Wait 15 millisecond for query change in global query
12821288 // if query changes, return so that it won't be calculated
1283- await Task.Delay(15, _updateSource.Token);
1284- if (_updateSource.Token.IsCancellationRequested)
1285- return;
1289+ await Task.Delay(15, _updateToken);
1290+ if (_updateToken.IsCancellationRequested) return;
12861291 }*/
12871292
1288- _ = Task . Delay ( 200 , _updateSource . Token ) . ContinueWith ( _ =>
1293+ _ = Task . Delay ( 200 , _updateToken ) . ContinueWith ( _ =>
12891294 {
12901295 // start the progress bar if query takes more than 200 ms and this is the current running query and it didn't finish yet
12911296 if ( _isQueryRunning )
12921297 {
12931298 ProgressBarVisibility = Visibility . Visible ;
12941299 }
12951300 } ,
1296- _updateSource . Token ,
1301+ _updateToken ,
12971302 TaskContinuationOptions . NotOnCanceled ,
12981303 TaskScheduler . Default ) ;
12991304
13001305 // plugins are ICollection, meaning LINQ will get the Count and preallocate Array
13011306
13021307 var tasks = plugins . Select ( plugin => plugin . Metadata . Disabled switch
13031308 {
1304- false => QueryTaskAsync ( plugin , _updateSource . Token ) ,
1309+ false => QueryTaskAsync ( plugin , _updateToken ) ,
13051310 true => Task . CompletedTask
13061311 } ) . ToArray ( ) ;
13071312
@@ -1315,13 +1320,13 @@ private async Task QueryResultsAsync(bool searchDelay, bool isReQuery = false, b
13151320 // nothing to do here
13161321 }
13171322
1318- if ( _updateSource . Token . IsCancellationRequested ) return ;
1323+ if ( _updateToken . IsCancellationRequested ) return ;
13191324
13201325 // this should happen once after all queries are done so progress bar should continue
13211326 // until the end of all querying
13221327 _isQueryRunning = false ;
13231328
1324- if ( ! _updateSource . Token . IsCancellationRequested )
1329+ if ( ! _updateToken . IsCancellationRequested )
13251330 {
13261331 // update to hidden if this is still the current query
13271332 ProgressBarVisibility = Visibility . Hidden ;
0 commit comments