Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 以线程安全的方式创建新窗口_C#_Wpf_Signalr - Fatal编程技术网

C# 以线程安全的方式创建新窗口

C# 以线程安全的方式创建新窗口,c#,wpf,signalr,C#,Wpf,Signalr,我使用信号器将消息向上推送到服务器,向下推送到特定的客户端 当我发送消息时,接收客户端从我的signalR服务器发送一个ReceiveMessage函数调用,该调用映射到我的应用程序中的静态类函数。然后,静态类尝试执行newchat()(我的消息窗口类)以在接收端打开消息窗口 这个抛出的调用线程必须是STA,因为许多UI组件都需要它。 我以前曾与代表一起处理过简单的表单元素(比如更改文本框),但我不知道如何在这种情况下应用它。当我读到Invoke时,它是在某种形式的表单对象上调用的,在我的情况下

我使用信号器将消息向上推送到服务器,向下推送到特定的客户端

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

这个抛出的调用线程必须是STA,因为许多UI组件都需要它。

我以前曾与代表一起处理过简单的表单元素(比如更改文本框),但我不知道如何在这种情况下应用它。当我读到
Invoke
时,它是在某种形式的表单对象上调用的,在我的情况下它不存在吗

TLDR;如何从静态类函数调用创建和显示表单的新实例最简单的方法:使用在GUI线程上执行创建:

App.MainWindow.Dispatcher.BeginInvoke((Action)(() => { new Chat(); }));
SynchronizationContext syncContext = SynchronizationContext.Current;
更难:创建一个新的STA线程,并在其上创建新窗口

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

Easter:使用在GUI线程上执行创建:

App.MainWindow.Dispatcher.BeginInvoke((Action)(() => { new Chat(); }));
SynchronizationContext syncContext = SynchronizationContext.Current;
更难:创建一个新的STA线程,并在其上创建新窗口


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

使用当前GUI的线程调度程序。然后调用invoke。典型例子:

Application.Current.Dispatcher.Invoke(() => { 
      var win = new Window();
      win.show(); 
});

使用当前GUI的线程调度程序。然后调用invoke。典型例子:

Application.Current.Dispatcher.Invoke(() => { 
      var win = new Window();
      win.show(); 
});

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

App.MainWindow.Dispatcher.BeginInvoke((Action)(() => { new Chat(); }));
SynchronizationContext syncContext = SynchronizationContext.Current;
在此,您可以参考上下文

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

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

                }, ...);
lambda表达式中的代码代表UI线程执行。
据我所知,在“Control.Invoke”和“Dispatcher.Invoked”两种方法中,这实际上都是在幕后发生的。

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

App.MainWindow.Dispatcher.BeginInvoke((Action)(() => { new Chat(); }));
SynchronizationContext syncContext = SynchronizationContext.Current;
在此,您可以参考上下文

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

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

                }, ...);
lambda表达式中的代码代表UI线程执行。
据我所知,在“Control.Invoke”和“Dispatcher.Invoked”两种方法中,这实际上都是在幕后发生的。

请注意,您应该注意BeginInvoke()和Invoke()方法之间的区别——前者将在另一个线程上异步执行操作,而后者则同步执行操作。调用调用,因为它们是同步的,在某些情况下可能会导致死锁,因此应仅在适当时使用。请参阅注意,您应该注意BeginInvoke()和Invoke()方法之间的区别——前者将在另一个线程上异步执行操作,而后者将同步执行操作。调用调用,因为它们是同步的,在某些情况下可能会导致死锁,因此应仅在适当时使用。看见