Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.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表单#_C#_Wpf_Multithreading - Fatal编程技术网

C# 如何从c中的不同线程构造新的WPF表单#

C# 如何从c中的不同线程构造新的WPF表单#,c#,wpf,multithreading,C#,Wpf,Multithreading,我对线程的概念以及如何使用线程有困难 我正在尝试编写一个相当基本的聊天程序(作为更大程序的一部分),它目前的工作方式如下: “NetworkSession”类在循环中的一个单独线程上接收来自服务器的输入。如果它收到指示它应该打开一个新的聊天窗口的输入,它将构造一个新的WPF类(聊天窗口)并显示它 最初我得到的错误是“调用线程必须是STA,因为许多UI组件都需要它。”。所以我将线程设置为STA,但现在WPF表单当然不可用,因为它与阻塞循环运行在同一线程上 所以我的问题是如何从另一个线程中创建WPF

我对线程的概念以及如何使用线程有困难

我正在尝试编写一个相当基本的聊天程序(作为更大程序的一部分),它目前的工作方式如下:

“NetworkSession”类在循环中的一个单独线程上接收来自服务器的输入。如果它收到指示它应该打开一个新的聊天窗口的输入,它将构造一个新的WPF类(聊天窗口)并显示它

最初我得到的错误是“调用线程必须是STA,因为许多UI组件都需要它。”。所以我将线程设置为STA,但现在WPF表单当然不可用,因为它与阻塞循环运行在同一线程上

所以我的问题是如何从另一个线程中创建WPF表单的新实例

我已经看到了很多关于这方面的讨论,但它倾向于处理从已经构建的表单运行委托的问题

下面是一些代码

while (Connected) //this loop is running on its own thread
        {



            Resp = srReceiver.ReadLine();
            if (Resp.StartsWith("PING")) SendToServer("PONG");

            if (Resp.StartsWith("CHAT FROM"))
            {

                String[] split = Resp.Split(' ');
                Console.WriteLine("Incoming Chat from {0}", split[2]);
                bool found = false;
                if (Chats.Count != 0)
                {
                    foreach (ChatWindow cw in Chats)
                    {
                        if (cw.User == split[2])
                        {
                            found = true;
                            cw.AddLine(cw.User, split[3]); // a function that adds a line to the current chat
                        }

                    }
                }
                if (!found)
                {

                        ChatWindow temp = new ChatWindow(split[2], split[3]);
                        Chats.Add(temp); //this is a collection with T = ChatWindow
                        temp.Show();

                }

            }

        }

您真正需要做的是在主UI线程上构造窗口/表单。您可能需要定义一个可以从网络线程调用的委托,并且该委托应该附加一个方法来调用此.Dispatcher.BeginInvoke()->,您将在其中构造窗口

this.Dispatcher.BeginInvoke()调用是在UI线程上执行代码所必需的,否则即使使用委托,代码也会在网络线程上执行


委托和创建新聊天窗口的方法可能都应该附加到主窗口…

如果您正在从UI线程构建NetworkSession,您可以找到对当前
调度程序的引用,该调度程序可在以后操作UI

NetworkSession.cs

private Dispatcher _dispatcher;

public NetworkSession()
{
   _dispatcher = Dispatcher.CurrentDispatcher;
}

//any thread can call this method
public void DoStuff()
{
   Action action = () =>
   {
      ChatWindow temp = new ChatWindow(split[2], split[3]);
      Chats.Add(temp);
      temp.Show();
   };

   _dispatcher.BeginInvoke(action);
}

下面的代码是我从中提取的,为我工作:

    public static void StartChatWindow()
    {
        Thread thread = new Thread(() =>
        {
            ChatWindow chatWindow = new ChatWindow();
            chatWindow.Chat(); // Do your stuff here, may pass some parameters

            chatWindow.Closed += (sender2, e2) =>
                // Close the message pump when the window closed
            chatWindow.Dispatcher.InvokeShutdown();

            // Run the message pump
            System.Windows.Threading.Dispatcher.Run();
        });

        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
    }