1

我正在使用 signalR 将消息向上推送到服务器并向下推送到特定客户端。

当我发送消息时,接收客户端会从我的 signalR 服务器发送一个 ReceiveMessage 函数调用,该函数调用映射到我的应用程序中的静态类函数。然后静态类尝试做new Chat()(我的消息窗口类)在接收端打开一个消息窗口。

这抛出calling thread must be STA, because many UI components require this.

我之前曾与代表一起处理简单的表单元素(例如更改文本框),但我不明白如何在这种情况下应用它。当我阅读 aboutInvoke时,它在某种形式的对象上被调用,这在我的情况下不存在?

TLDR;如何从静态类函数调用创建和显示表单的新实例

4

3 回答 3

5

使用当前 GUI 的线程调度程序。然后调用invoke。标准杆示例:

Application.Current.Dispatcher.Invoke(() => { 
      var win = new Window();
      win.show(); 
});
于 2012-07-30T14:44:39.947 回答
2

最简单:利用App.MainWindow.Dispatcher在 GUI 线程上执行创建:

App.MainWindow.Dispatcher.BeginInvoke((Action)(() => { new Chat(); }));

更难:创建一个新的 STA 线程,并在其上创建新的 Window。

后一种选择更难,因为您将拥有多个 GUI 线程,并且需要确保跟踪操作,以便在每种情况下都使用正确的线程。除非您有特定的理由让多个 GUI 线程坚持使用简单选项。

于 2012-07-30T14:41:43.193 回答
0

您必须在 UI 线程中调用您的代码。为此,您需要参考同步上下文。假设您从 UI 线程调用了以下代码:

SynchronizationContext syncContext = SynchronizationContext.Current;

因此,您得到了对上下文的参考。

然后在回调方法中(在后台线程(不是UI)中接收到消息后)你可以执行以下操作:

syncContext.Post((state) =>
                {
                    Window w = new Window(); 

                }, ...);

lambda 表达式中的代码代表 UI 线程执行。据我所知,这就是“Control.Invoke”和“Dispatcher.Invoked”方法在幕后实际发生的情况。

于 2012-07-30T14:49:03.517 回答