@@ -127,34 +127,39 @@ private async System.Threading.Tasks.Task RefreshAllTabsAsync(int hoursBack, Dat
127127 {
128128 var loadSw = Stopwatch . StartNew ( ) ;
129129
130- /* Load all tabs in parallel */
131- var snapshotsTask = _dataService . GetLatestQuerySnapshotsAsync ( _serverId , hoursBack , fromDate , toDate ) ;
132- var cpuTask = _dataService . GetCpuUtilizationAsync ( _serverId , hoursBack , fromDate , toDate ) ;
133- var memoryTask = _dataService . GetLatestMemoryStatsAsync ( _serverId ) ;
134- var memoryTrendTask = _dataService . GetMemoryTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ;
135- var queryStatsTask = _dataService . GetTopQueriesByCpuAsync ( _serverId , hoursBack , 50 , fromDate , toDate , UtcOffsetMinutes ) ;
136- var procStatsTask = _dataService . GetTopProceduresByCpuAsync ( _serverId , hoursBack , 50 , fromDate , toDate , UtcOffsetMinutes ) ;
137- var fileIoTrendTask = _dataService . GetFileIoLatencyTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ;
138- var fileIoThroughputTask = _dataService . GetFileIoThroughputTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ;
139- var tempDbTask = _dataService . GetTempDbTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ;
140- var tempDbFileIoTask = _dataService . GetTempDbFileIoTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ;
141- var deadlockTask = _dataService . GetRecentDeadlocksAsync ( _serverId , hoursBack , fromDate , toDate ) ;
142- var blockedProcessTask = _dataService . GetRecentBlockedProcessReportsAsync ( _serverId , hoursBack , fromDate , toDate ) ;
143- var waitTypesTask = _dataService . GetDistinctWaitTypesAsync ( _serverId , hoursBack , fromDate , toDate ) ;
144- var memoryClerkTypesTask = _dataService . GetDistinctMemoryClerkTypesAsync ( _serverId , hoursBack , fromDate , toDate ) ;
145- var perfmonCountersTask = _dataService . GetDistinctPerfmonCountersAsync ( _serverId , hoursBack , fromDate , toDate ) ;
146- var queryStoreTask = _dataService . GetQueryStoreTopQueriesAsync ( _serverId , hoursBack , 50 , fromDate , toDate ) ;
147- var memoryGrantTrendTask = _dataService . GetMemoryGrantTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ;
148- var memoryGrantChartTask = _dataService . GetMemoryGrantChartDataAsync ( _serverId , hoursBack , fromDate , toDate ) ;
149- var memoryPressureEventsTask = _dataService . GetMemoryPressureEventsAsync ( _serverId , hoursBack , fromDate , toDate ) ;
150- var serverConfigTask = SafeQueryAsync ( ( ) => _dataService . GetLatestServerConfigAsync ( _serverId ) ) ;
151- var databaseConfigTask = SafeQueryAsync ( ( ) => _dataService . GetLatestDatabaseConfigAsync ( _serverId ) ) ;
152- var databaseScopedConfigTask = SafeQueryAsync ( ( ) => _dataService . GetLatestDatabaseScopedConfigAsync ( _serverId ) ) ;
153- var traceFlagsTask = SafeQueryAsync ( ( ) => _dataService . GetLatestTraceFlagsAsync ( _serverId ) ) ;
154- var runningJobsTask = SafeQueryAsync ( ( ) => _dataService . GetRunningJobsAsync ( _serverId ) ) ;
155- var collectionHealthTask = SafeQueryAsync ( ( ) => _dataService . GetCollectionHealthAsync ( _serverId ) ) ;
156- var collectionLogTask = SafeQueryAsync ( ( ) => _dataService . GetRecentCollectionLogAsync ( _serverId , hoursBack ) ) ;
157- var dailySummaryTask = _dataService . GetDailySummaryAsync ( _serverId , _dailySummaryDate ) ;
130+ /* Load all tabs in parallel, off the UI thread.
131+ DuckDB.NET is synchronous, so calling these directly on the dispatcher would run all
132+ ~36 queries serially on the UI thread (the freeze). Task.Run pushes each onto a pool
133+ thread — each query's read lock is acquired AND released inside that one synchronous run,
134+ so the ReaderWriterLockSlim thread affinity is respected — and the fan-out below becomes
135+ genuinely parallel. The UI-update code after the awaits is unchanged. */
136+ var snapshotsTask = Task . Run ( ( ) => _dataService . GetLatestQuerySnapshotsAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
137+ var cpuTask = Task . Run ( ( ) => _dataService . GetCpuUtilizationAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
138+ var memoryTask = Task . Run ( ( ) => _dataService . GetLatestMemoryStatsAsync ( _serverId ) ) ;
139+ var memoryTrendTask = Task . Run ( ( ) => _dataService . GetMemoryTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
140+ var queryStatsTask = Task . Run ( ( ) => _dataService . GetTopQueriesByCpuAsync ( _serverId , hoursBack , 50 , fromDate , toDate , UtcOffsetMinutes ) ) ;
141+ var procStatsTask = Task . Run ( ( ) => _dataService . GetTopProceduresByCpuAsync ( _serverId , hoursBack , 50 , fromDate , toDate , UtcOffsetMinutes ) ) ;
142+ var fileIoTrendTask = Task . Run ( ( ) => _dataService . GetFileIoLatencyTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
143+ var fileIoThroughputTask = Task . Run ( ( ) => _dataService . GetFileIoThroughputTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
144+ var tempDbTask = Task . Run ( ( ) => _dataService . GetTempDbTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
145+ var tempDbFileIoTask = Task . Run ( ( ) => _dataService . GetTempDbFileIoTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
146+ var deadlockTask = Task . Run ( ( ) => _dataService . GetRecentDeadlocksAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
147+ var blockedProcessTask = Task . Run ( ( ) => _dataService . GetRecentBlockedProcessReportsAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
148+ var waitTypesTask = Task . Run ( ( ) => _dataService . GetDistinctWaitTypesAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
149+ var memoryClerkTypesTask = Task . Run ( ( ) => _dataService . GetDistinctMemoryClerkTypesAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
150+ var perfmonCountersTask = Task . Run ( ( ) => _dataService . GetDistinctPerfmonCountersAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
151+ var queryStoreTask = Task . Run ( ( ) => _dataService . GetQueryStoreTopQueriesAsync ( _serverId , hoursBack , 50 , fromDate , toDate ) ) ;
152+ var memoryGrantTrendTask = Task . Run ( ( ) => _dataService . GetMemoryGrantTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
153+ var memoryGrantChartTask = Task . Run ( ( ) => _dataService . GetMemoryGrantChartDataAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
154+ var memoryPressureEventsTask = Task . Run ( ( ) => _dataService . GetMemoryPressureEventsAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
155+ var serverConfigTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetLatestServerConfigAsync ( _serverId ) ) ) ;
156+ var databaseConfigTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetLatestDatabaseConfigAsync ( _serverId ) ) ) ;
157+ var databaseScopedConfigTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetLatestDatabaseScopedConfigAsync ( _serverId ) ) ) ;
158+ var traceFlagsTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetLatestTraceFlagsAsync ( _serverId ) ) ) ;
159+ var runningJobsTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetRunningJobsAsync ( _serverId ) ) ) ;
160+ var collectionHealthTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetCollectionHealthAsync ( _serverId ) ) ) ;
161+ var collectionLogTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetRecentCollectionLogAsync ( _serverId , hoursBack ) ) ) ;
162+ var dailySummaryTask = Task . Run ( ( ) => _dataService . GetDailySummaryAsync ( _serverId , _dailySummaryDate ) ) ;
158163 /* Core data tasks */
159164 await System . Threading . Tasks . Task . WhenAll (
160165 snapshotsTask , cpuTask , memoryTask , memoryTrendTask ,
@@ -165,15 +170,15 @@ await System.Threading.Tasks.Task.WhenAll(
165170 runningJobsTask , collectionHealthTask , collectionLogTask , dailySummaryTask ) ;
166171
167172 /* Trend chart tasks - run separately so failures don't kill the whole refresh */
168- var lockWaitTrendTask = SafeQueryAsync ( ( ) => _dataService . GetLockWaitTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
169- var blockingTrendTask = SafeQueryAsync ( ( ) => _dataService . GetBlockingTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
170- var deadlockTrendTask = SafeQueryAsync ( ( ) => _dataService . GetDeadlockTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
171- var queryDurationTrendTask = SafeQueryAsync ( ( ) => _dataService . GetQueryDurationTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
172- var procDurationTrendTask = SafeQueryAsync ( ( ) => _dataService . GetProcedureDurationTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
173- var queryStoreDurationTrendTask = SafeQueryAsync ( ( ) => _dataService . GetQueryStoreDurationTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
174- var executionCountTrendTask = SafeQueryAsync ( ( ) => _dataService . GetExecutionCountTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
175- var currentWaitsDurationTask = SafeQueryAsync ( ( ) => _dataService . GetWaitingTaskTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
176- var currentWaitsBlockedTask = SafeQueryAsync ( ( ) => _dataService . GetBlockedSessionTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ;
173+ var lockWaitTrendTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetLockWaitTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ) ;
174+ var blockingTrendTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetBlockingTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ) ;
175+ var deadlockTrendTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetDeadlockTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ) ;
176+ var queryDurationTrendTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetQueryDurationTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ) ;
177+ var procDurationTrendTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetProcedureDurationTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ) ;
178+ var queryStoreDurationTrendTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetQueryStoreDurationTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ) ;
179+ var executionCountTrendTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetExecutionCountTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ) ;
180+ var currentWaitsDurationTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetWaitingTaskTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ) ;
181+ var currentWaitsBlockedTask = Task . Run ( ( ) => SafeQueryAsync ( ( ) => _dataService . GetBlockedSessionTrendAsync ( _serverId , hoursBack , fromDate , toDate ) ) ) ;
177182
178183 await System . Threading . Tasks . Task . WhenAll (
179184 lockWaitTrendTask , blockingTrendTask , deadlockTrendTask ,
0 commit comments