UI线程分离解决卡顿问题

This commit is contained in:
PeterZhong 2025-06-01 16:04:38 +08:00
parent 7a3516f855
commit d58510e29c
2 changed files with 53 additions and 17 deletions

View File

@ -8,10 +8,10 @@ using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
using System.Windows.Documents; using System.Windows.Documents;
using System.Xml; using System.Xml;
using System.Xml.Linq; using System.Xml.Linq;
using ArcGIS.Desktop.Framework.Dialogs;
using ArcGIS.Desktop.Internal.Mapping.Locate; using ArcGIS.Desktop.Internal.Mapping.Locate;
using LinkToolAddin.client; using LinkToolAddin.client;
using LinkToolAddin.client.prompt; using LinkToolAddin.client.prompt;
@ -33,6 +33,7 @@ using Newtonsoft.Json.Schema.Generation;
using Tool = LinkToolAddin.host.mcp.Tool; using Tool = LinkToolAddin.host.mcp.Tool;
using LinkToolAddin.common; using LinkToolAddin.common;
using LinkToolAddin.host.llm.entity.stream; using LinkToolAddin.host.llm.entity.stream;
using MessageBox = ArcGIS.Desktop.Framework.Dialogs.MessageBox;
namespace LinkToolAddin.host; namespace LinkToolAddin.host;
@ -300,7 +301,10 @@ public class Gateway
type = MessageType.REASON_MESSAGE, type = MessageType.REASON_MESSAGE,
id = (timestamp-1).ToString() id = (timestamp-1).ToString()
}; };
Application.Current.Dispatcher.Invoke(() =>
{
callback?.Invoke(reasonMessageListItem); callback?.Invoke(reasonMessageListItem);
});
messageContent = chunk; messageContent = chunk;
var (matched, remaining) = ExtractMatchedPart(chunk, toolPattern); var (matched, remaining) = ExtractMatchedPart(chunk, toolPattern);
if (matched == "") if (matched == "")
@ -316,7 +320,10 @@ public class Gateway
type = MessageType.CHAT_MESSAGE, type = MessageType.CHAT_MESSAGE,
id = timestamp.ToString() id = timestamp.ToString()
}; };
Application.Current.Dispatcher.Invoke(() =>
{
callback?.Invoke(chatMessageListItem); callback?.Invoke(chatMessageListItem);
});
} }
else else
{ {
@ -352,7 +359,10 @@ public class Gateway
type = MessageType.CHAT_MESSAGE, type = MessageType.CHAT_MESSAGE,
id = timestamp.ToString() id = timestamp.ToString()
}; };
Application.Current.Dispatcher.Invoke(() =>
{
callback?.Invoke(chatMessageListItem); callback?.Invoke(chatMessageListItem);
});
XElement toolUse = XElement.Parse(matched); XElement toolUse = XElement.Parse(matched);
string fullToolName = toolUse.Element("name")?.Value; string fullToolName = toolUse.Element("name")?.Value;
string toolArgs = toolUse.Element("arguments")?.Value; string toolArgs = toolUse.Element("arguments")?.Value;
@ -414,7 +424,10 @@ public class Gateway
? SystemPrompt.ErrorPrompt(JsonConvert.SerializeObject(toolResponse)) ? SystemPrompt.ErrorPrompt(JsonConvert.SerializeObject(toolResponse))
: SystemPrompt.ContinuePrompt(JsonConvert.SerializeObject(toolResponse)) : SystemPrompt.ContinuePrompt(JsonConvert.SerializeObject(toolResponse))
}); });
Application.Current.Dispatcher.Invoke(() =>
{
callback?.Invoke(toolMessageItem); callback?.Invoke(toolMessageItem);
});
} }
else if (mcpServer is StdioMcpServer) else if (mcpServer is StdioMcpServer)
{ {
@ -437,7 +450,10 @@ public class Gateway
? SystemPrompt.ErrorPrompt(JsonConvert.SerializeObject(toolResponse)) ? SystemPrompt.ErrorPrompt(JsonConvert.SerializeObject(toolResponse))
: SystemPrompt.ContinuePrompt(JsonConvert.SerializeObject(toolResponse)) : SystemPrompt.ContinuePrompt(JsonConvert.SerializeObject(toolResponse))
}); });
Application.Current.Dispatcher.Invoke(() =>
{
callback?.Invoke(toolMessageItem); callback?.Invoke(toolMessageItem);
});
} }
else if (mcpServer is InnerMcpServer) else if (mcpServer is InnerMcpServer)
{ {
@ -477,7 +493,10 @@ public class Gateway
Role = "user", Role = "user",
Content = SystemPrompt.ErrorPrompt(JsonConvert.SerializeObject(toolMessageItem)) Content = SystemPrompt.ErrorPrompt(JsonConvert.SerializeObject(toolMessageItem))
}); });
Application.Current.Dispatcher.Invoke(() =>
{
callback?.Invoke(toolMessageItem); callback?.Invoke(toolMessageItem);
});
} }
else if (innerResult is JsonRpcSuccessEntity) else if (innerResult is JsonRpcSuccessEntity)
{ {
@ -495,7 +514,10 @@ public class Gateway
Role = "user", Role = "user",
Content = SystemPrompt.ContinuePrompt(JsonConvert.SerializeObject(toolMessageItem)) Content = SystemPrompt.ContinuePrompt(JsonConvert.SerializeObject(toolMessageItem))
}); });
Application.Current.Dispatcher.Invoke(() =>
{
callback?.Invoke(toolMessageItem); callback?.Invoke(toolMessageItem);
});
} }
} }
} }
@ -526,7 +548,10 @@ public class Gateway
content = "成功调用提示词:"+promptRequest.PromptName, content = "成功调用提示词:"+promptRequest.PromptName,
id = (timestamp+1).ToString() id = (timestamp+1).ToString()
}; };
Application.Current.Dispatcher.Invoke(() =>
{
callback?.Invoke(toolMessageItem); callback?.Invoke(toolMessageItem);
});
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
@ -37,7 +38,7 @@ namespace LinkToolAddin.ui.dockpane
private static ILog log = LogManager.GetLogger(typeof(TestDockpaneView)); private static ILog log = LogManager.GetLogger(typeof(TestDockpaneView));
private List<string> idList = new List<string>(); private List<string> idList = new List<string>();
private Dictionary<string,MessageListItem> messageDict = new Dictionary<string,MessageListItem>(); private ConcurrentDictionary<string,MessageListItem> messageDict = new ConcurrentDictionary<string,MessageListItem>();
public TestDockpaneView() public TestDockpaneView()
{ {
@ -197,13 +198,13 @@ namespace LinkToolAddin.ui.dockpane
log.Info(msg.content); log.Info(msg.content);
} }
private void PromptTestButton_OnClick(object sender, RoutedEventArgs e) private async void PromptTestButton_OnClick(object sender, RoutedEventArgs e)
{ {
string userPrompt = PromptTestTextBox.Text; string userPrompt = PromptTestTextBox.Text;
// model可选值qwen3-235b-a22b,qwen-max,deepseek-r1 // model可选值qwen3-235b-a22b,qwen-max,deepseek-r1
try try
{ {
Gateway.SendMessageStream(userPrompt,"qwen3-235b-a22b", "D:\\01_Project\\20250305_LinkTool\\20250420_AiDemoProject\\20250420_AiDemoProject.gdb", AddReplyStream); await Task.Run(() => Gateway.SendMessageStream(userPrompt,"qwen3-235b-a22b", "D:\\01_Project\\20250305_LinkTool\\20250420_AiDemoProject\\20250420_AiDemoProject.gdb", AddReplyStream));
} }
catch (Exception exception) catch (Exception exception)
{ {
@ -211,7 +212,12 @@ namespace LinkToolAddin.ui.dockpane
} }
} }
public void AddReplyStream(MessageListItem msg) public async void AddReplyStream(MessageListItem msg)
{
await Task.Run(() => ProcessReplyStream(msg));
}
private void ProcessReplyStream(MessageListItem msg)
{ {
string id = msg.id; string id = msg.id;
if (idList.Contains(id)) if (idList.Contains(id))
@ -221,9 +227,12 @@ namespace LinkToolAddin.ui.dockpane
else else
{ {
idList.Add(id); idList.Add(id);
messageDict.Add(msg.id, msg); messageDict.TryAdd(msg.id, msg);
} }
Application.Current.Dispatcher.Invoke(() =>
{
ReplyTextBox.Clear(); ReplyTextBox.Clear();
});
try try
{ {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
@ -237,14 +246,16 @@ namespace LinkToolAddin.ui.dockpane
} }
builder.AppendLine(content); builder.AppendLine(content);
builder.AppendLine(); builder.AppendLine();
}
Application.Current.Dispatcher.Invoke(() =>
{
ReplyTextBox.Text = builder.ToString(); ReplyTextBox.Text = builder.ToString();
ReplyTextBox.ScrollToEnd(); ReplyTextBox.ScrollToEnd();
} });
}catch (Exception exception) }catch (Exception exception)
{ {
log.Error(exception.Message); log.Error(exception.Message);
} }
} }
public void AddReply(MessageListItem msg) public void AddReply(MessageListItem msg)