diff --git a/host/Gateway.cs b/host/Gateway.cs index cb9a0fb..2a789c5 100644 --- a/host/Gateway.cs +++ b/host/Gateway.cs @@ -8,10 +8,10 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using System.Windows; using System.Windows.Documents; using System.Xml; using System.Xml.Linq; -using ArcGIS.Desktop.Framework.Dialogs; using ArcGIS.Desktop.Internal.Mapping.Locate; using LinkToolAddin.client; using LinkToolAddin.client.prompt; @@ -33,6 +33,7 @@ using Newtonsoft.Json.Schema.Generation; using Tool = LinkToolAddin.host.mcp.Tool; using LinkToolAddin.common; using LinkToolAddin.host.llm.entity.stream; +using MessageBox = ArcGIS.Desktop.Framework.Dialogs.MessageBox; namespace LinkToolAddin.host; @@ -300,7 +301,10 @@ public class Gateway type = MessageType.REASON_MESSAGE, id = (timestamp-1).ToString() }; - callback?.Invoke(reasonMessageListItem); + Application.Current.Dispatcher.Invoke(() => + { + callback?.Invoke(reasonMessageListItem); + }); messageContent = chunk; var (matched, remaining) = ExtractMatchedPart(chunk, toolPattern); if (matched == "") @@ -316,7 +320,10 @@ public class Gateway type = MessageType.CHAT_MESSAGE, id = timestamp.ToString() }; - callback?.Invoke(chatMessageListItem); + Application.Current.Dispatcher.Invoke(() => + { + callback?.Invoke(chatMessageListItem); + }); } else { @@ -352,7 +359,10 @@ public class Gateway type = MessageType.CHAT_MESSAGE, id = timestamp.ToString() }; - callback?.Invoke(chatMessageListItem); + Application.Current.Dispatcher.Invoke(() => + { + callback?.Invoke(chatMessageListItem); + }); XElement toolUse = XElement.Parse(matched); string fullToolName = toolUse.Element("name")?.Value; string toolArgs = toolUse.Element("arguments")?.Value; @@ -414,7 +424,10 @@ public class Gateway ? SystemPrompt.ErrorPrompt(JsonConvert.SerializeObject(toolResponse)) : SystemPrompt.ContinuePrompt(JsonConvert.SerializeObject(toolResponse)) }); - callback?.Invoke(toolMessageItem); + Application.Current.Dispatcher.Invoke(() => + { + callback?.Invoke(toolMessageItem); + }); } else if (mcpServer is StdioMcpServer) { @@ -437,7 +450,10 @@ public class Gateway ? SystemPrompt.ErrorPrompt(JsonConvert.SerializeObject(toolResponse)) : SystemPrompt.ContinuePrompt(JsonConvert.SerializeObject(toolResponse)) }); - callback?.Invoke(toolMessageItem); + Application.Current.Dispatcher.Invoke(() => + { + callback?.Invoke(toolMessageItem); + }); } else if (mcpServer is InnerMcpServer) { @@ -477,7 +493,10 @@ public class Gateway Role = "user", Content = SystemPrompt.ErrorPrompt(JsonConvert.SerializeObject(toolMessageItem)) }); - callback?.Invoke(toolMessageItem); + Application.Current.Dispatcher.Invoke(() => + { + callback?.Invoke(toolMessageItem); + }); } else if (innerResult is JsonRpcSuccessEntity) { @@ -495,7 +514,10 @@ public class Gateway Role = "user", Content = SystemPrompt.ContinuePrompt(JsonConvert.SerializeObject(toolMessageItem)) }); - callback?.Invoke(toolMessageItem); + Application.Current.Dispatcher.Invoke(() => + { + callback?.Invoke(toolMessageItem); + }); } } } @@ -526,7 +548,10 @@ public class Gateway content = "成功调用提示词:"+promptRequest.PromptName, id = (timestamp+1).ToString() }; - callback?.Invoke(toolMessageItem); + Application.Current.Dispatcher.Invoke(() => + { + callback?.Invoke(toolMessageItem); + }); } catch (Exception e) { diff --git a/ui/dockpane/TestDockpane.xaml.cs b/ui/dockpane/TestDockpane.xaml.cs index 374e8c3..267b7ea 100644 --- a/ui/dockpane/TestDockpane.xaml.cs +++ b/ui/dockpane/TestDockpane.xaml.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -37,7 +38,7 @@ namespace LinkToolAddin.ui.dockpane private static ILog log = LogManager.GetLogger(typeof(TestDockpaneView)); private List idList = new List(); - private Dictionary messageDict = new Dictionary(); + private ConcurrentDictionary messageDict = new ConcurrentDictionary(); public TestDockpaneView() { @@ -197,13 +198,13 @@ namespace LinkToolAddin.ui.dockpane 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; // model可选值:qwen3-235b-a22b,qwen-max,deepseek-r1 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) { @@ -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; if (idList.Contains(id)) @@ -221,9 +227,12 @@ namespace LinkToolAddin.ui.dockpane else { idList.Add(id); - messageDict.Add(msg.id, msg); + messageDict.TryAdd(msg.id, msg); } - ReplyTextBox.Clear(); + Application.Current.Dispatcher.Invoke(() => + { + ReplyTextBox.Clear(); + }); try { StringBuilder builder = new StringBuilder(); @@ -237,14 +246,16 @@ namespace LinkToolAddin.ui.dockpane } builder.AppendLine(content); builder.AppendLine(); + } + Application.Current.Dispatcher.Invoke(() => + { ReplyTextBox.Text = builder.ToString(); ReplyTextBox.ScrollToEnd(); - } + }); }catch (Exception exception) { log.Error(exception.Message); } - } public void AddReply(MessageListItem msg)