refactor: use System.Threading.CancellationToken instead of SourceGit.Commands.Command.CancelToken to cancel fetching information of selected commit

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo 2025-03-11 16:53:51 +08:00
parent f23e3478e6
commit 471452646b
No known key found for this signature in database
2 changed files with 40 additions and 43 deletions

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading;
using Avalonia.Threading; using Avalonia.Threading;
@ -10,11 +11,6 @@ namespace SourceGit.Commands
{ {
public partial class Command public partial class Command
{ {
public class CancelToken
{
public bool Requested { get; set; } = false;
}
public class ReadToEndResult public class ReadToEndResult
{ {
public bool IsSuccess { get; set; } = false; public bool IsSuccess { get; set; } = false;
@ -30,7 +26,7 @@ namespace SourceGit.Commands
} }
public string Context { get; set; } = string.Empty; public string Context { get; set; } = string.Empty;
public CancelToken Cancel { get; set; } = null; public CancellationToken CancellationToken { get; set; } = CancellationToken.None;
public string WorkingDirectory { get; set; } = null; public string WorkingDirectory { get; set; } = null;
public EditorType Editor { get; set; } = EditorType.CoreEditor; // Only used in Exec() mode public EditorType Editor { get; set; } = EditorType.CoreEditor; // Only used in Exec() mode
public string SSHKey { get; set; } = string.Empty; public string SSHKey { get; set; } = string.Empty;
@ -43,36 +39,15 @@ namespace SourceGit.Commands
var start = CreateGitStartInfo(); var start = CreateGitStartInfo();
var errs = new List<string>(); var errs = new List<string>();
var proc = new Process() { StartInfo = start }; var proc = new Process() { StartInfo = start };
var isCancelled = false;
proc.OutputDataReceived += (_, e) => proc.OutputDataReceived += (_, e) =>
{ {
if (Cancel != null && Cancel.Requested)
{
isCancelled = true;
proc.CancelErrorRead();
proc.CancelOutputRead();
if (!proc.HasExited)
proc.Kill(true);
return;
}
if (e.Data != null) if (e.Data != null)
OnReadline(e.Data); OnReadline(e.Data);
}; };
proc.ErrorDataReceived += (_, e) => proc.ErrorDataReceived += (_, e) =>
{ {
if (Cancel != null && Cancel.Requested)
{
isCancelled = true;
proc.CancelErrorRead();
proc.CancelOutputRead();
if (!proc.HasExited)
proc.Kill(true);
return;
}
if (string.IsNullOrEmpty(e.Data)) if (string.IsNullOrEmpty(e.Data))
{ {
errs.Add(string.Empty); errs.Add(string.Empty);
@ -97,9 +72,25 @@ namespace SourceGit.Commands
errs.Add(e.Data); errs.Add(e.Data);
}; };
var dummy = null as Process;
try try
{ {
proc.Start(); proc.Start();
// It not safe, please only use `CancellationToken` in readonly commands.
if (CancellationToken.CanBeCanceled)
{
dummy = proc;
CancellationToken.Register(() =>
{
if (dummy is { HasExited: false })
{
dummy.CancelErrorRead();
dummy.CancelOutputRead();
dummy.Kill();
}
});
}
} }
catch (Exception e) catch (Exception e)
{ {
@ -113,10 +104,11 @@ namespace SourceGit.Commands
proc.BeginErrorReadLine(); proc.BeginErrorReadLine();
proc.WaitForExit(); proc.WaitForExit();
dummy = null;
int exitCode = proc.ExitCode; int exitCode = proc.ExitCode;
proc.Close(); proc.Close();
if (!isCancelled && exitCode != 0) if (!CancellationToken.IsCancellationRequested && exitCode != 0)
{ {
if (RaiseError) if (RaiseError)
{ {

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
@ -171,7 +172,7 @@ namespace SourceGit.ViewModels
_searchChangeFilter = null; _searchChangeFilter = null;
_diffContext = null; _diffContext = null;
_viewRevisionFileContent = null; _viewRevisionFileContent = null;
_cancelToken = null; _cancellationSource = null;
WebLinks.Clear(); WebLinks.Clear();
_revisionFiles = null; _revisionFiles = null;
_revisionFileSearchSuggestion = null; _revisionFileSearchSuggestion = null;
@ -589,32 +590,36 @@ namespace SourceGit.ViewModels
if (_commit == null) if (_commit == null)
return; return;
if (_cancellationSource is { IsCancellationRequested: false })
_cancellationSource.Cancel();
_cancellationSource = new CancellationTokenSource();
var token = _cancellationSource.Token;
Task.Run(() => Task.Run(() =>
{ {
var message = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result(); var message = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result();
var links = ParseLinksInMessage(message); var links = ParseLinksInMessage(message);
if (!token.IsCancellationRequested)
Dispatcher.UIThread.Invoke(() => FullMessage = new Models.CommitFullMessage { Message = message, Links = links }); Dispatcher.UIThread.Invoke(() => FullMessage = new Models.CommitFullMessage { Message = message, Links = links });
}); });
Task.Run(() => Task.Run(() =>
{ {
var signInfo = new Commands.QueryCommitSignInfo(_repo.FullPath, _commit.SHA, !_repo.HasAllowedSignersFile).Result(); var signInfo = new Commands.QueryCommitSignInfo(_repo.FullPath, _commit.SHA, !_repo.HasAllowedSignersFile).Result();
if (!token.IsCancellationRequested)
Dispatcher.UIThread.Invoke(() => SignInfo = signInfo); Dispatcher.UIThread.Invoke(() => SignInfo = signInfo);
}); });
if (_cancelToken != null)
_cancelToken.Requested = true;
_cancelToken = new Commands.Command.CancelToken();
if (Preferences.Instance.ShowChildren) if (Preferences.Instance.ShowChildren)
{ {
Task.Run(() => Task.Run(() =>
{ {
var max = Preferences.Instance.MaxHistoryCommits; var max = Preferences.Instance.MaxHistoryCommits;
var cmdChildren = new Commands.QueryCommitChildren(_repo.FullPath, _commit.SHA, max) { Cancel = _cancelToken }; var cmd = new Commands.QueryCommitChildren(_repo.FullPath, _commit.SHA, max) { CancellationToken = token };
var children = cmdChildren.Result(); var children = cmd.Result();
if (!cmdChildren.Cancel.Requested) if (!token.IsCancellationRequested)
Dispatcher.UIThread.Post(() => Children = children); Dispatcher.UIThread.Post(() => Children = children);
}); });
} }
@ -622,8 +627,8 @@ namespace SourceGit.ViewModels
Task.Run(() => Task.Run(() =>
{ {
var parent = _commit.Parents.Count == 0 ? "4b825dc642cb6eb9a060e54bf8d69288fbee4904" : _commit.Parents[0]; var parent = _commit.Parents.Count == 0 ? "4b825dc642cb6eb9a060e54bf8d69288fbee4904" : _commit.Parents[0];
var cmdChanges = new Commands.CompareRevisions(_repo.FullPath, parent, _commit.SHA) { Cancel = _cancelToken }; var cmd = new Commands.CompareRevisions(_repo.FullPath, parent, _commit.SHA) { CancellationToken = token };
var changes = cmdChanges.Result(); var changes = cmd.Result();
var visible = changes; var visible = changes;
if (!string.IsNullOrWhiteSpace(_searchChangeFilter)) if (!string.IsNullOrWhiteSpace(_searchChangeFilter))
{ {
@ -635,7 +640,7 @@ namespace SourceGit.ViewModels
} }
} }
if (!cmdChanges.Cancel.Requested) if (!token.IsCancellationRequested)
{ {
Dispatcher.UIThread.Post(() => Dispatcher.UIThread.Post(() =>
{ {
@ -873,7 +878,7 @@ namespace SourceGit.ViewModels
private string _searchChangeFilter = string.Empty; private string _searchChangeFilter = string.Empty;
private DiffContext _diffContext = null; private DiffContext _diffContext = null;
private object _viewRevisionFileContent = null; private object _viewRevisionFileContent = null;
private Commands.Command.CancelToken _cancelToken = null; private CancellationTokenSource _cancellationSource = null;
private List<string> _revisionFiles = null; private List<string> _revisionFiles = null;
private string _revisionFileSearchFilter = string.Empty; private string _revisionFileSearchFilter = string.Empty;
private List<string> _revisionFileSearchSuggestion = null; private List<string> _revisionFileSearchSuggestion = null;