Skip to content

Commit 4714526

Browse files
committed
refactor: use System.Threading.CancellationToken instead of SourceGit.Commands.Command.CancelToken to cancel fetching information of selected commit
Signed-off-by: leo <[email protected]>
1 parent f23e347 commit 4714526

File tree

2 files changed

+40
-43
lines changed

2 files changed

+40
-43
lines changed

src/Commands/Command.cs

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,14 @@
33
using System.Diagnostics;
44
using System.Text;
55
using System.Text.RegularExpressions;
6+
using System.Threading;
67

78
using Avalonia.Threading;
89

910
namespace SourceGit.Commands
1011
{
1112
public partial class Command
1213
{
13-
public class CancelToken
14-
{
15-
public bool Requested { get; set; } = false;
16-
}
17-
1814
public class ReadToEndResult
1915
{
2016
public bool IsSuccess { get; set; } = false;
@@ -30,7 +26,7 @@ public enum EditorType
3026
}
3127

3228
public string Context { get; set; } = string.Empty;
33-
public CancelToken Cancel { get; set; } = null;
29+
public CancellationToken CancellationToken { get; set; } = CancellationToken.None;
3430
public string WorkingDirectory { get; set; } = null;
3531
public EditorType Editor { get; set; } = EditorType.CoreEditor; // Only used in Exec() mode
3632
public string SSHKey { get; set; } = string.Empty;
@@ -43,36 +39,15 @@ public bool Exec()
4339
var start = CreateGitStartInfo();
4440
var errs = new List<string>();
4541
var proc = new Process() { StartInfo = start };
46-
var isCancelled = false;
4742

4843
proc.OutputDataReceived += (_, e) =>
4944
{
50-
if (Cancel != null && Cancel.Requested)
51-
{
52-
isCancelled = true;
53-
proc.CancelErrorRead();
54-
proc.CancelOutputRead();
55-
if (!proc.HasExited)
56-
proc.Kill(true);
57-
return;
58-
}
59-
6045
if (e.Data != null)
6146
OnReadline(e.Data);
6247
};
6348

6449
proc.ErrorDataReceived += (_, e) =>
6550
{
66-
if (Cancel != null && Cancel.Requested)
67-
{
68-
isCancelled = true;
69-
proc.CancelErrorRead();
70-
proc.CancelOutputRead();
71-
if (!proc.HasExited)
72-
proc.Kill(true);
73-
return;
74-
}
75-
7651
if (string.IsNullOrEmpty(e.Data))
7752
{
7853
errs.Add(string.Empty);
@@ -97,9 +72,25 @@ public bool Exec()
9772
errs.Add(e.Data);
9873
};
9974

75+
var dummy = null as Process;
10076
try
10177
{
10278
proc.Start();
79+
80+
// It not safe, please only use `CancellationToken` in readonly commands.
81+
if (CancellationToken.CanBeCanceled)
82+
{
83+
dummy = proc;
84+
CancellationToken.Register(() =>
85+
{
86+
if (dummy is { HasExited: false })
87+
{
88+
dummy.CancelErrorRead();
89+
dummy.CancelOutputRead();
90+
dummy.Kill();
91+
}
92+
});
93+
}
10394
}
10495
catch (Exception e)
10596
{
@@ -113,10 +104,11 @@ public bool Exec()
113104
proc.BeginErrorReadLine();
114105
proc.WaitForExit();
115106

107+
dummy = null;
116108
int exitCode = proc.ExitCode;
117109
proc.Close();
118110

119-
if (!isCancelled && exitCode != 0)
111+
if (!CancellationToken.IsCancellationRequested && exitCode != 0)
120112
{
121113
if (RaiseError)
122114
{

src/ViewModels/CommitDetail.cs

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Globalization;
44
using System.IO;
55
using System.Text.RegularExpressions;
6+
using System.Threading;
67
using System.Threading.Tasks;
78

89
using Avalonia.Controls;
@@ -171,7 +172,7 @@ public void Cleanup()
171172
_searchChangeFilter = null;
172173
_diffContext = null;
173174
_viewRevisionFileContent = null;
174-
_cancelToken = null;
175+
_cancellationSource = null;
175176
WebLinks.Clear();
176177
_revisionFiles = null;
177178
_revisionFileSearchSuggestion = null;
@@ -589,41 +590,45 @@ private void Refresh()
589590
if (_commit == null)
590591
return;
591592

593+
if (_cancellationSource is { IsCancellationRequested: false })
594+
_cancellationSource.Cancel();
595+
596+
_cancellationSource = new CancellationTokenSource();
597+
var token = _cancellationSource.Token;
598+
592599
Task.Run(() =>
593600
{
594601
var message = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result();
595602
var links = ParseLinksInMessage(message);
596-
Dispatcher.UIThread.Invoke(() => FullMessage = new Models.CommitFullMessage { Message = message, Links = links });
603+
604+
if (!token.IsCancellationRequested)
605+
Dispatcher.UIThread.Invoke(() => FullMessage = new Models.CommitFullMessage { Message = message, Links = links });
597606
});
598607

599608
Task.Run(() =>
600609
{
601610
var signInfo = new Commands.QueryCommitSignInfo(_repo.FullPath, _commit.SHA, !_repo.HasAllowedSignersFile).Result();
602-
Dispatcher.UIThread.Invoke(() => SignInfo = signInfo);
611+
if (!token.IsCancellationRequested)
612+
Dispatcher.UIThread.Invoke(() => SignInfo = signInfo);
603613
});
604614

605-
if (_cancelToken != null)
606-
_cancelToken.Requested = true;
607-
608-
_cancelToken = new Commands.Command.CancelToken();
609-
610615
if (Preferences.Instance.ShowChildren)
611616
{
612617
Task.Run(() =>
613618
{
614619
var max = Preferences.Instance.MaxHistoryCommits;
615-
var cmdChildren = new Commands.QueryCommitChildren(_repo.FullPath, _commit.SHA, max) { Cancel = _cancelToken };
616-
var children = cmdChildren.Result();
617-
if (!cmdChildren.Cancel.Requested)
620+
var cmd = new Commands.QueryCommitChildren(_repo.FullPath, _commit.SHA, max) { CancellationToken = token };
621+
var children = cmd.Result();
622+
if (!token.IsCancellationRequested)
618623
Dispatcher.UIThread.Post(() => Children = children);
619624
});
620625
}
621626

622627
Task.Run(() =>
623628
{
624629
var parent = _commit.Parents.Count == 0 ? "4b825dc642cb6eb9a060e54bf8d69288fbee4904" : _commit.Parents[0];
625-
var cmdChanges = new Commands.CompareRevisions(_repo.FullPath, parent, _commit.SHA) { Cancel = _cancelToken };
626-
var changes = cmdChanges.Result();
630+
var cmd = new Commands.CompareRevisions(_repo.FullPath, parent, _commit.SHA) { CancellationToken = token };
631+
var changes = cmd.Result();
627632
var visible = changes;
628633
if (!string.IsNullOrWhiteSpace(_searchChangeFilter))
629634
{
@@ -635,7 +640,7 @@ private void Refresh()
635640
}
636641
}
637642

638-
if (!cmdChanges.Cancel.Requested)
643+
if (!token.IsCancellationRequested)
639644
{
640645
Dispatcher.UIThread.Post(() =>
641646
{
@@ -873,7 +878,7 @@ private void CalcRevisionFileSearchSuggestion()
873878
private string _searchChangeFilter = string.Empty;
874879
private DiffContext _diffContext = null;
875880
private object _viewRevisionFileContent = null;
876-
private Commands.Command.CancelToken _cancelToken = null;
881+
private CancellationTokenSource _cancellationSource = null;
877882
private List<string> _revisionFiles = null;
878883
private string _revisionFileSearchFilter = string.Empty;
879884
private List<string> _revisionFileSearchSuggestion = null;

0 commit comments

Comments
 (0)