2010-10-16 4 views
2

У меня возникли проблемы с концепцией потоков и их использованием.Как создать новую форму WPF из другого потока в C#

Я пытаюсь кодировать довольно основную программу чата (как часть более крупной программы), и в настоящее время он работает так:

класс «NetworkSession» получает входные данные от сервера в отдельном потоке в петля. Если он получает ввод, который указывает, что он должен открыть новое окно чата, он создает новый класс WPF (ChatWindow) и отображает его.

Первоначально я получил сообщение об ошибке, что «вызывающий поток должен быть STA, потому что для этого требуется множество компонентов пользовательского интерфейса». Поэтому я установил поток в 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(); 

       } 

      } 

     } 

ответ

3

Если вы построение NetworkSession от вашего UI темы, вы можете поймать ссылку на текущий Dispatcher которые могут манипулировать интерфейсом позже.

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); 
} 
0

Что вам нужно сделать, это построить окно/форму на основной теме пользовательского интерфейса. Вероятно, вам нужно определить делегата, который вы можете вызывать из сетевого потока, и что делегат должен иметь прикрепленный метод, который вызывается this.Dispatcher.BeginInvoke() -> внутри которого вы будете строить свое окно.

Этот вызов.Dispatcher.BeginInvoke() необходим для выполнения кода в потоке пользовательского интерфейса, в противном случае даже с делегатом код будет выполняться в сетевом потоке.

Как делегат и метод для создания нового окна чата, вероятно, следует прикрепить к MainWindow ...

1

ниже код, который я взял из here работал для меня:

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(); 
    } 
Смежные вопросы