Skip to content

Commit 3485db2

Browse files
committed
Analogy hangs on huge exception messages #1781.
1 parent 2506b9a commit 3485db2

File tree

6 files changed

+81
-44
lines changed

6 files changed

+81
-44
lines changed

Analogy.CommonControls/Tools/JsonTreeUC.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public JsonTreeUC(string json):this()
3535
JsonData = json;
3636
_useRawField = false;
3737
}
38-
private void JsonTreeUC_Load(object sender, EventArgs e)
38+
private async void JsonTreeUC_Load(object sender, EventArgs e)
3939
{
4040
if (DesignMode)
4141
{
@@ -51,13 +51,13 @@ private void JsonTreeUC_Load(object sender, EventArgs e)
5151
JsonData = Utils.ExtractJsonObject(_useRawField ? Message.RawText : Message.Text);
5252
if (!string.IsNullOrEmpty(JsonData))
5353
{
54-
_jsonTreeView.ShowJson(JsonData);
54+
await _jsonTreeView.ShowJson(JsonData);
5555
}
5656
return;
5757
}
5858
if (!string.IsNullOrEmpty(JsonData))
5959
{
60-
_jsonTreeView.ShowJson(JsonData);
60+
await _jsonTreeView.ShowJson(JsonData);
6161
}
6262

6363
bbiCopyMessage.ItemClick += (_, _) =>
@@ -66,12 +66,12 @@ private void JsonTreeUC_Load(object sender, EventArgs e)
6666
};
6767
}
6868

69-
public void ShowJson(string json)
69+
public async Task ShowJson(string json)
7070
{
7171
JsonData = json;
7272
if (!string.IsNullOrEmpty(JsonData))
7373
{
74-
_jsonTreeView.ShowJson(JsonData);
74+
await _jsonTreeView.ShowJson(JsonData);
7575
}
7676
}
7777

Analogy.CommonControls/Tools/JsonTreeView.cs

+57-21
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.ComponentModel;
34
using System.Drawing;
45
using System.Linq;
56
using System.Runtime.CompilerServices;
7+
using System.Threading;
8+
using System.Threading.Tasks;
69
using System.Windows.Forms;
710
using Analogy.CommonControls.Properties;
11+
using DevExpress.Office.Utils;
812
using Newtonsoft.Json;
913
using Newtonsoft.Json.Linq;
1014

@@ -21,17 +25,19 @@ public class JsonTreeView : TreeView
2125
private ToolStripMenuItem expandAllMenuItem;
2226
private StatusStrip statusStrip1;
2327
private string previouslySelectedNodeText;
28+
private CancellationTokenSource cancellationTokenSource;
2429
public event EventHandler<string> OnNodeChanged;
2530
public string Message { get; set; }
2631
public JsonTreeView()
2732
{
2833
InitializeComponent();
34+
cancellationTokenSource = new CancellationTokenSource();
2935
AfterSelect += this_AfterSelect;
3036
DoubleClick += (s, e) =>
3137
{
3238
if (SelectedNode != null)
3339
{
34-
Clipboard.SetText(SelectedNode.Text,TextDataFormat.UnicodeText);
40+
Clipboard.SetText(SelectedNode.Text, TextDataFormat.UnicodeText);
3541
}
3642
};
3743
MouseDown += this_MouseDown;
@@ -113,21 +119,25 @@ private void LoadImageList()
113119
}
114120

115121
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
116-
private void LoadTree(object jsonData)
122+
private List<TreeNode> LoadTree(object jsonData, CancellationToken cancellationToken)
117123
{
118-
Nodes.Clear();
124+
if (cancellationToken.IsCancellationRequested)
125+
{
126+
return new();
127+
}
128+
List<TreeNode> nodes = new();
119129
if (jsonData is JArray jsonArray)
120130
{
121131
var rootNode = new JsonTreeNode(JsonNodeType.Object, "(root array)");
122132
foreach (JToken jToken in jsonArray)
123133
{
124134
var node = new JsonTreeNode(JsonNodeType.Array, jToken.Type.ToString());
125135
rootNode.Nodes.Add(node);
126-
LoadObject(jToken as JObject, node);
136+
LoadObject(jToken as JObject, node, cancellationToken);
127137
}
128138
TreeNode[] rootNodeArray = new TreeNode[rootNode.Nodes.Count];
129139
rootNode.Nodes.CopyTo(rootNodeArray, 0);
130-
Nodes.Add(rootNode);
140+
nodes.Add(rootNode);
131141
SelectedNode = rootNodeArray.First() as JsonTreeNode;
132142
rootNode.ImageKey = rootNode.NodeType.ToString();
133143
rootNode.SelectedImageKey = rootNode.ImageKey;
@@ -137,13 +147,15 @@ private void LoadTree(object jsonData)
137147
if (jsonData is JObject json)
138148
{
139149
var rootNode = new JsonTreeNode(JsonNodeType.Object, "(root)");
140-
Nodes.Add(rootNode);
150+
nodes.Add(rootNode);
141151
SelectedNode = rootNode;
142152
rootNode.ImageKey = rootNode.NodeType.ToString();
143153
rootNode.SelectedImageKey = rootNode.ImageKey;
144-
LoadObject(json, rootNode);
154+
LoadObject(json, rootNode, cancellationToken);
145155
rootNode.ExpandAll();
146156
}
157+
158+
return nodes;
147159
}
148160
[MethodImpl(MethodImplOptions.AggressiveInlining)]
149161
private static bool TryParse(string strInput, out JToken output)
@@ -182,52 +194,66 @@ private static bool TryParse(string strInput, out JToken output)
182194
return false;
183195
}
184196
}
185-
private void AddNode(JsonTreeNode parentNode, string property, JToken item)
197+
private void AddNode(JsonTreeNode parentNode, string property, JToken item, CancellationToken cancellationToken)
186198
{
199+
if (cancellationToken.IsCancellationRequested)
200+
{
201+
return;
202+
}
203+
187204
var node = JsonTreeNodeCreator.CreateNode(property, item);
188205
parentNode.Nodes.Add(node);
189206
if (item.Type == JTokenType.Array)
190207
{
191-
LoadArray(item, node);
208+
LoadArray(item, node, cancellationToken);
192209
}
193210

194211
else if (item.Type == JTokenType.Object)
195212
{
196-
LoadObject(item as JObject, node);
213+
LoadObject(item as JObject, node, cancellationToken);
197214
}
198215
else if (TryParse(item.ToString(), out var token))
199216
{
200217
node.Text = property;
201218
if (token.Type == JTokenType.Array)
202219
{
203-
LoadArray(token, node);
220+
LoadArray(token, node, cancellationToken);
204221
}
205222

206223
else if (token.Type == JTokenType.Object)
207224
{
208-
LoadObject(token as JObject, node);
225+
LoadObject(token as JObject, node, cancellationToken);
209226
}
210227
}
211228
}
212229

213-
private void LoadArray(JToken value, JsonTreeNode node)
230+
private void LoadArray(JToken value, JsonTreeNode node, CancellationToken cancellationToken)
214231
{
232+
if (cancellationToken.IsCancellationRequested)
233+
{
234+
return;
235+
}
215236
foreach (var item in value)
216237
{
217-
AddNode(node, null, item);
238+
AddNode(node, null, item, cancellationToken);
218239
}
219240
}
220241

221-
private void LoadObject(JObject obj, JsonTreeNode node)
242+
private void LoadObject(JObject obj, JsonTreeNode node, CancellationToken cancellationToken)
222243
{
244+
if (cancellationToken.IsCancellationRequested)
245+
{
246+
return;
247+
}
248+
223249
if (obj is null)
224250
{
225251
return;
226252
}
227253

228254
foreach (var item in obj)
229255
{
230-
AddNode(node, item.Key, item.Value);
256+
AddNode(node, item.Key, item.Value, cancellationToken);
231257
}
232258
}
233259

@@ -280,7 +306,7 @@ private void InitializeComponent()
280306
get => base.SelectedNode as JsonTreeNode;
281307
set => base.SelectedNode = value;
282308
}
283-
309+
284310
private void this_AfterSelect(object sender, TreeViewEventArgs e)
285311
{
286312
// restore previous seelcted node text and store the next
@@ -292,9 +318,9 @@ private void this_AfterSelect(object sender, TreeViewEventArgs e)
292318
previouslySelectedNodeText = e.Node.Text;
293319

294320
e.Node.Text = ((JsonTreeNode)e.Node).TextWhenSelected;
295-
OnNodeChanged?.Invoke(this,e.Node.Text);
321+
OnNodeChanged?.Invoke(this, e.Node.Text);
296322
}
297-
323+
298324
private void this_MouseDown(object sender, MouseEventArgs e)
299325
{
300326
if (e.Button == MouseButtons.Right)
@@ -330,13 +356,23 @@ public void ClearList()
330356
{
331357
Nodes.Clear();
332358
}
333-
public void ShowJson(string jsonString)
359+
public async Task ShowJson(string jsonString)
334360
{
335361
Message = jsonString;
336362
try
337363
{
364+
BeginUpdate();
365+
Nodes.Clear();
366+
cancellationTokenSource?.Cancel();
367+
cancellationTokenSource = new CancellationTokenSource();
368+
var token = cancellationTokenSource.Token;
338369
object json = JsonConvert.DeserializeObject(jsonString);
339-
LoadTree(json);
370+
var nodes = await Task.Run(() => LoadTree(json, token));
371+
if (!token.IsCancellationRequested)
372+
{
373+
Nodes.AddRange(nodes.ToArray());
374+
}
375+
EndUpdate();
340376
}
341377
catch (Exception e)
342378
{

Analogy.CommonControls/Tools/JsonViewerForm.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public JsonViewerForm(string json, IUserSettingsManager settings) : this(setting
3333
JsonData = json;
3434
_useRawField = false;
3535
}
36-
private void JsonViewerForm_Load(object sender, EventArgs e)
36+
private async void JsonViewerForm_Load(object sender, EventArgs e)
3737
{
3838
if (DesignMode)
3939
{
@@ -52,22 +52,22 @@ private void JsonViewerForm_Load(object sender, EventArgs e)
5252
if (!string.IsNullOrEmpty(JsonData))
5353
{
5454
memoEdit1.Text = JsonData;
55-
_jsonTreeView.ShowJson(JsonData);
55+
await _jsonTreeView.ShowJson(JsonData);
5656
}
5757
else if (Message != null)
5858
{
5959
memoEdit1.Text = _useRawField ? Message.RawText : Message.Text;
6060
JsonData = Utils.ExtractJsonObject(_useRawField ? Message.RawText : Message.Text);
6161
if (!string.IsNullOrEmpty(JsonData))
6262
{
63-
_jsonTreeView.ShowJson(JsonData);
63+
await _jsonTreeView.ShowJson(JsonData);
6464
}
6565
}
6666
}
6767

68-
private void sbtnLoad_Click(object sender, EventArgs e)
68+
private async void sbtnLoad_Click(object sender, EventArgs e)
6969
{
70-
_jsonTreeView.ShowJson(memoEdit1.Text);
70+
await _jsonTreeView.ShowJson(memoEdit1.Text);
7171
}
7272
}
7373
}

Analogy.CommonControls/UserControls/LogMessagesUC.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -3304,7 +3304,7 @@ private void bBtnSaveEntireLog_ItemClick(object sender, ItemClickEventArgs e)
33043304
SaveMessagesToLog(FileDataProvider, messages);
33053305
}
33063306

3307-
private void logGrid_FocusedRowChanged(object sender, FocusedRowChangedEventArgs e)
3307+
private async void logGrid_FocusedRowChanged(object sender, FocusedRowChangedEventArgs e)
33083308
{
33093309
int row = e.FocusedRowHandle;
33103310

@@ -3321,12 +3321,12 @@ private void logGrid_FocusedRowChanged(object sender, FocusedRowChangedEventArgs
33213321
if (useSpecificColumnForJson)
33223322
{
33233323
var specific = LogGrid.GetRowCellValue(e.FocusedRowHandle, jsonColumnForInlineJsonViewer).ToString();
3324-
JsonTreeView.ShowJson(specific);
3324+
await JsonTreeView.ShowJson(specific);
33253325

33263326
}
33273327
else if (focusedMassage.RawTextType == AnalogyRowTextType.JSON)
33283328
{
3329-
JsonTreeView.ShowJson(focusedMassage.RawText);
3329+
await JsonTreeView.ShowJson(focusedMassage.RawText);
33303330
}
33313331
}
33323332

Analogy.CommonControls/UserControls/MessageDetailsUC.cs

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Threading.Tasks;
45
using System.Windows.Forms;
56
using Analogy.Common;
67
using Analogy.Common.Interfaces;
@@ -32,7 +33,7 @@ public MessageDetailsUC(AnalogyLogMessage msg, List<IAnalogyLogMessage> messages
3233
DataSource = dataSource;
3334
}
3435

35-
private void UCMessageDetails_Load(object sender, EventArgs e)
36+
private async void UCMessageDetails_Load(object sender, EventArgs e)
3637
{
3738
if (DesignMode)
3839
{
@@ -46,7 +47,7 @@ private void UCMessageDetails_Load(object sender, EventArgs e)
4647
_jsonTreeView = new JsonTreeUC();
4748
splitContainerControl1.Panel2.Controls.Add(_jsonTreeView);
4849
_jsonTreeView.Dock = DockStyle.Fill;
49-
LoadMessage();
50+
await LoadMessage();
5051
}
5152
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
5253
{
@@ -66,7 +67,7 @@ protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
6667

6768
}
6869

69-
public void LoadMessage()
70+
public async Task LoadMessage()
7071
{
7172
if (Message == null)
7273
{
@@ -105,7 +106,7 @@ public void LoadMessage()
105106
_jsonTreeView.ClearList();
106107
if (!string.IsNullOrEmpty(json))
107108
{
108-
_jsonTreeView.ShowJson(json);
109+
await _jsonTreeView.ShowJson(json);
109110
}
110111

111112
splitContainerControl1.PanelVisibility = SplitPanelVisibility.Both;
@@ -122,25 +123,25 @@ private void btnNext_Click(object sender, EventArgs e)
122123
LoadNextMessage();
123124
}
124125

125-
private void LoadPreviousMessage()
126+
private async void LoadPreviousMessage()
126127
{
127128
if (Messages.First() == Message)
128129
{
129130
return;
130131
}
131132

132133
Message = Messages[Messages.IndexOf(Message) - 1];
133-
LoadMessage();
134+
await LoadMessage();
134135
}
135-
private void LoadNextMessage()
136+
private async void LoadNextMessage()
136137
{
137138
if (Messages.Last() == Message)
138139
{
139140
return;
140141
}
141142

142143
Message = Messages[Messages.IndexOf(Message) + 1];
143-
LoadMessage();
144+
await LoadMessage();
144145
}
145146
private void btnPrev_Click(object sender, EventArgs e)
146147
{

Analogy.CommonControls/UserControls/ServerSideLogMessagesUC.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3067,7 +3067,7 @@ private void bBtnSaveEntireLog_ItemClick(object sender, ItemClickEventArgs e)
30673067
SaveMessagesToLog(FileDataProvider, messages);
30683068
}
30693069

3070-
private void logGrid_FocusedRowChanged(object sender, FocusedRowChangedEventArgs e)
3070+
private async void logGrid_FocusedRowChanged(object sender, FocusedRowChangedEventArgs e)
30713071
{
30723072
int row = e.FocusedRowHandle;
30733073

@@ -3081,7 +3081,7 @@ private void logGrid_FocusedRowChanged(object sender, FocusedRowChangedEventArgs
30813081
LoadTextBoxes(focusedMassage);
30823082
if (Settings.InlineJsonViewer && focusedMassage.RawTextType == AnalogyRowTextType.JSON)
30833083
{
3084-
JsonTreeView.ShowJson(focusedMassage.RawText);
3084+
await JsonTreeView.ShowJson(focusedMassage.RawText);
30853085
}
30863086
string dataProvider = (string)LogGrid.GetRowCellValue(e.FocusedRowHandle, "DataProvider");
30873087
if (!LoadingInProgress)

0 commit comments

Comments
 (0)