Skip to content

Commit f80ae30

Browse files
committed
CherryPick Exception Optimize
1 parent fe859f6 commit f80ae30

File tree

6 files changed

+122
-102
lines changed

6 files changed

+122
-102
lines changed

Flow.Launcher.Core/Plugin/PluginManager.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public static ICollection<PluginPair> ValidPluginsForQuery(Query query)
157157
}
158158
}
159159

160-
public static async Task<List<Result>> QueryForPlugin(PluginPair pair, Query query, CancellationToken token)
160+
public static async Task<List<Result>> QueryForPluginAsync(PluginPair pair, Query query, CancellationToken token)
161161
{
162162
var results = new List<Result>();
163163
try
@@ -171,7 +171,7 @@ public static async Task<List<Result>> QueryForPlugin(PluginPair pair, Query que
171171

172172
token.ThrowIfCancellationRequested();
173173
if (results == null)
174-
return results;
174+
return null;
175175
UpdatePluginMetadata(results, metadata, query);
176176

177177
metadata.QueryCount += 1;
@@ -184,10 +184,6 @@ public static async Task<List<Result>> QueryForPlugin(PluginPair pair, Query que
184184
// null will be fine since the results will only be added into queue if the token hasn't been cancelled
185185
return null;
186186
}
187-
catch (Exception e)
188-
{
189-
Log.Exception($"|PluginManager.QueryForPlugin|Exception for plugin <{pair.Metadata.Name}> when query <{query}>", e);
190-
}
191187

192188
return results;
193189
}

Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
</ItemGroup>
5050

5151
<ItemGroup>
52+
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
53+
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="16.10.56" />
5254
<PackageReference Include="NLog.Schema" Version="4.7.0-rc1" />
5355
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.0" />
5456
<PackageReference Include="System.Drawing.Common" Version="4.7.0" />

Flow.Launcher.Infrastructure/Logger/Log.cs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
using NLog.Config;
66
using NLog.Targets;
77
using Flow.Launcher.Infrastructure.UserSettings;
8+
using JetBrains.Annotations;
9+
using NLog.Targets.Wrappers;
10+
using System.Runtime.ExceptionServices;
811

912
namespace Flow.Launcher.Infrastructure.Logger
1013
{
@@ -23,11 +26,13 @@ static Log()
2326
}
2427

2528
var configuration = new LoggingConfiguration();
26-
var target = new FileTarget();
27-
configuration.AddTarget("file", target);
28-
target.FileName = CurrentLogDirectory.Replace(@"\", "/") + "/${shortdate}.txt";
29+
var fileTarget = new FileTarget();
30+
fileTarget.FileName = CurrentLogDirectory.Replace(@"\", "/") + "/${shortdate}.txt";
31+
32+
var fileTargetASyncWrapper = new AsyncTargetWrapper(fileTarget);
33+
configuration.AddTarget("file", fileTargetASyncWrapper);
2934
#if DEBUG
30-
var rule = new LoggingRule("*", LogLevel.Debug, target);
35+
var rule = new LoggingRule("*", LogLevel.Debug, fileTargetASyncWrapper);
3136
#else
3237
var rule = new LoggingRule("*", LogLevel.Info, target);
3338
#endif
@@ -50,13 +55,12 @@ private static bool FormatValid(string message)
5055
return valid;
5156
}
5257

53-
54-
55-
[MethodImpl(MethodImplOptions.Synchronized)]
58+
5659
public static void Exception(string className, string message, System.Exception exception, [CallerMemberName] string methodName = "")
57-
{
60+
{
61+
exception = exception.Demystify();
5862
#if DEBUG
59-
throw exception;
63+
ExceptionDispatchInfo.Capture(exception).Throw();
6064
#else
6165
var classNameWithMethod = CheckClassAndMessageAndReturnFullClassWithMethod(className, message, methodName);
6266

@@ -131,8 +135,9 @@ private static void LogInternal(string message, LogLevel level)
131135
[MethodImpl(MethodImplOptions.Synchronized)]
132136
public static void Exception(string message, System.Exception e)
133137
{
138+
e = e.Demystify();
134139
#if DEBUG
135-
throw e;
140+
ExceptionDispatchInfo.Capture(e).Throw();
136141
#else
137142
if (FormatValid(message))
138143
{

Flow.Launcher/ViewModel/MainViewModel.cs

Lines changed: 86 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
using Flow.Launcher.Plugin.SharedCommands;
2020
using Flow.Launcher.Storage;
2121
using Flow.Launcher.Infrastructure.Logger;
22+
using Microsoft.VisualStudio.Threading;
2223
using System.Threading.Channels;
2324
using ISavable = Flow.Launcher.Plugin.ISavable;
25+
using System.Windows.Threading;
2426

2527
namespace Flow.Launcher.ViewModel
2628
{
@@ -110,15 +112,17 @@ async Task updateAction()
110112
}
111113

112114
Log.Error("MainViewModel", "Unexpected ResultViewUpdate ends");
113-
};
115+
}
116+
117+
;
114118

115119
void continueAction(Task t)
116120
{
117121
#if DEBUG
118122
throw t.Exception;
119123
#else
120124
Log.Error($"Error happen in task dealing with viewupdate for results. {t.Exception}");
121-
_resultsViewUpdateTask =
125+
_resultsViewUpdateTask =
122126
Task.Run(updateAction).ContinueWith(continueAction, TaskContinuationOptions.OnlyOnFaulted);
123127
#endif
124128
}
@@ -137,7 +141,8 @@ private void RegisterResultsUpdatedEvent()
137141
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(e.Results, pair.Metadata, e.Query, _updateToken)))
138142
{
139143
Log.Error("MainViewModel", "Unable to add item to Result Update Queue");
140-
};
144+
}
145+
;
141146
}
142147
};
143148
}
@@ -237,21 +242,24 @@ private void InitializeKeyCommands()
237242

238243
ReloadPluginDataCommand = new RelayCommand(_ =>
239244
{
240-
var msg = new Msg { Owner = Application.Current.MainWindow };
245+
var msg = new Msg
246+
{
247+
Owner = Application.Current.MainWindow
248+
};
241249

242250
MainWindowVisibility = Visibility.Collapsed;
243251

244252
PluginManager
245-
.ReloadData()
246-
.ContinueWith(_ =>
247-
Application.Current.Dispatcher.Invoke(() =>
248-
{
249-
msg.Show(
250-
InternationalizationManager.Instance.GetTranslation("success"),
251-
InternationalizationManager.Instance.GetTranslation("completedSuccessfully"),
252-
"");
253-
}))
254-
.ConfigureAwait(false);
253+
.ReloadData()
254+
.ContinueWith(_ =>
255+
Application.Current.Dispatcher.Invoke(() =>
256+
{
257+
msg.Show(
258+
InternationalizationManager.Instance.GetTranslation("success"),
259+
InternationalizationManager.Instance.GetTranslation("completedSuccessfully"),
260+
"");
261+
}))
262+
.ConfigureAwait(false);
255263
});
256264
}
257265

@@ -422,7 +430,10 @@ private void QueryHistory()
422430
Title = string.Format(title, h.Query),
423431
SubTitle = string.Format(time, h.ExecutedDateTime),
424432
IcoPath = "Images\\history.png",
425-
OriginQuery = new Query { RawQuery = h.Query },
433+
OriginQuery = new Query
434+
{
435+
RawQuery = h.Query
436+
},
426437
Action = _ =>
427438
{
428439
SelectedResults = Results;
@@ -448,7 +459,9 @@ private void QueryHistory()
448459
}
449460
}
450461

451-
private void QueryResults()
462+
private readonly IReadOnlyList<Result> _emptyResult = new List<Result>();
463+
464+
private async void QueryResults()
452465
{
453466
_updateSource?.Cancel();
454467

@@ -478,74 +491,73 @@ private void QueryResults()
478491

479492
var plugins = PluginManager.ValidPluginsForQuery(query);
480493

481-
Task.Run(async () =>
494+
if (query.ActionKeyword == Plugin.Query.GlobalPluginWildcardSign)
495+
{
496+
// Wait 45 millisecond for query change in global query
497+
// if query changes, return so that it won't be calculated
498+
await Task.Delay(45, currentCancellationToken);
499+
if (currentCancellationToken.IsCancellationRequested)
500+
return;
501+
}
502+
503+
_ = Task.Delay(200, currentCancellationToken).ContinueWith(_ =>
504+
{
505+
// start the progress bar if query takes more than 200 ms and this is the current running query and it didn't finish yet
506+
if (!currentCancellationToken.IsCancellationRequested && _isQueryRunning)
482507
{
483-
if (query.ActionKeyword == Plugin.Query.GlobalPluginWildcardSign)
484-
{
485-
// Wait 45 millisecond for query change in global query
486-
// if query changes, return so that it won't be calculated
487-
await Task.Delay(45, currentCancellationToken);
488-
if (currentCancellationToken.IsCancellationRequested)
489-
return;
490-
}
508+
ProgressBarVisibility = Visibility.Visible;
509+
}
510+
}, currentCancellationToken, TaskContinuationOptions.NotOnCanceled, TaskScheduler.Default);
491511

492-
_ = Task.Delay(200, currentCancellationToken).ContinueWith(_ =>
493-
{
494-
// start the progress bar if query takes more than 200 ms and this is the current running query and it didn't finish yet
495-
if (!currentCancellationToken.IsCancellationRequested && _isQueryRunning)
496-
{
497-
ProgressBarVisibility = Visibility.Visible;
498-
}
499-
}, currentCancellationToken);
512+
// plugins is ICollection, meaning LINQ will get the Count and preallocate Array
500513

501-
// plugins is ICollection, meaning LINQ will get the Count and preallocate Array
514+
var tasks = plugins.Select(plugin => plugin.Metadata.Disabled switch
515+
{
516+
false => QueryTask(plugin),
517+
true => Task.CompletedTask
518+
}).ToArray();
502519

503-
Task[] tasks = plugins.Select(plugin => plugin.Metadata.Disabled switch
504-
{
505-
false => QueryTask(plugin),
506-
true => Task.CompletedTask
507-
}).ToArray();
508520

509-
try
510-
{
511-
// Check the code, WhenAll will translate all type of IEnumerable or Collection to Array, so make an array at first
512-
await Task.WhenAll(tasks);
513-
}
514-
catch (OperationCanceledException)
515-
{
516-
// nothing to do here
517-
}
521+
try
522+
{
523+
// Check the code, WhenAll will translate all type of IEnumerable or Collection to Array, so make an array at first
524+
await Task.WhenAll(tasks);
525+
}
526+
catch (OperationCanceledException)
527+
{
528+
// nothing to do here
529+
}
518530

519-
if (currentCancellationToken.IsCancellationRequested)
520-
return;
531+
if (currentCancellationToken.IsCancellationRequested)
532+
return;
521533

522-
// this should happen once after all queries are done so progress bar should continue
523-
// until the end of all querying
524-
_isQueryRunning = false;
525-
if (!currentCancellationToken.IsCancellationRequested)
526-
{
527-
// update to hidden if this is still the current query
528-
ProgressBarVisibility = Visibility.Hidden;
529-
}
534+
// this should happen once after all queries are done so progress bar should continue
535+
// until the end of all querying
536+
_isQueryRunning = false;
537+
if (!currentCancellationToken.IsCancellationRequested)
538+
{
539+
// update to hidden if this is still the current query
540+
ProgressBarVisibility = Visibility.Hidden;
541+
}
530542

531-
// Local function
532-
async Task QueryTask(PluginPair plugin)
533-
{
534-
// Since it is wrapped within a Task.Run, the synchronous context is null
535-
// Task.Yield will force it to run in ThreadPool
536-
await Task.Yield();
543+
// Local function
544+
async Task QueryTask(PluginPair plugin)
545+
{
546+
// Since it is wrapped within a Task.Run, the synchronous context is null
547+
// Task.Yield will force it to run in ThreadPool
548+
await Task.Yield();
537549

538-
var results = await PluginManager.QueryForPlugin(plugin, query, currentCancellationToken);
539-
if (currentCancellationToken.IsCancellationRequested || results == null) return;
550+
IReadOnlyList<Result> results = await PluginManager.QueryForPluginAsync(plugin, query, currentCancellationToken);
551+
552+
currentCancellationToken.ThrowIfCancellationRequested();
540553

541-
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(results, plugin.Metadata, query, currentCancellationToken)))
542-
{
543-
Log.Error("MainViewModel", "Unable to add item to Result Update Queue");
544-
};
545-
}
546-
}, currentCancellationToken)
547-
.ContinueWith(t => Log.Exception("|MainViewModel|Plugins Query Exceptions", t.Exception),
548-
TaskContinuationOptions.OnlyOnFaulted);
554+
results ??= _emptyResult;
555+
556+
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(results, plugin.Metadata, query, currentCancellationToken)))
557+
{
558+
Log.Error("MainViewModel", "Unable to add item to Result Update Queue");
559+
}
560+
}
549561
}
550562

551563

Flow.Launcher/ViewModel/ResultsForUpdate.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ namespace Flow.Launcher.ViewModel
88
{
99
public struct ResultsForUpdate
1010
{
11-
public List<Result> Results { get; }
11+
public IReadOnlyList<Result> Results { get; }
1212

1313
public PluginMetadata Metadata { get; }
1414
public string ID { get; }
1515

1616
public Query Query { get; }
1717
public CancellationToken Token { get; }
1818

19-
public ResultsForUpdate(List<Result> results, PluginMetadata metadata, Query query, CancellationToken token)
19+
public ResultsForUpdate(IReadOnlyList<Result> results, PluginMetadata metadata, Query query, CancellationToken token)
2020
{
2121
Results = results;
2222
Metadata = metadata;

0 commit comments

Comments
 (0)