2017-02-13 19 views
0

В настоящее время я работаю над проектом, где я получаю фреймы как bytearray и отображаю их в GUI (WPF). Сейчас я неудовлетворен производительностью, потому что кадры становятся отображаемыми с задержкой. Итак, я подумал о том, как делать многопоточность, так что сокет и графический интерфейс работают независимо друг от друга. Однако, если я пытаюсь запустить socketRoutine в отдельном потоке, я получаю сообщение об ошибке, что поток не может получить доступ к ресурсу другого потока.C# Передача данных между потоками, легко

Я не уверен, что такое ресурс. Я предполагаю, что это либо bytearray im, проходящий в GUI, либо компонент GUI, к которому нужно получить доступ.

Это мой код прямо сейчас.

namespace Subscriber_WPF{ 
/// <summary> 
/// Interaction logic for MainWindow.xaml 
/// </summary> 
/// 

public partial class MainWindow : Window{ 

    /*Kinect Datentypen*/ 
    private WriteableBitmap colorBitmap = null; 
    static readonly String publisherID = "TYPE1"; 

    SocketHandler socketHandler; 
    Thread socketThread; 

    public MainWindow(){  
     ConsoleManager.Show(); 
     colorBitmap = new WriteableBitmap(1920, 1080, 96.0, 96.0, PixelFormats.Bgra32, null); 
     this.DataContext = this; 

     //initializeKinectComponents(); 
     socketHandler = new SocketHandler(5555, publisherID, this); 
     socketThread = new Thread(()=>socketHandler.runSocketRoutine()); 

     Console.WriteLine("GUI-Components initialized. Press Enter to start receiving Frames."); 

     this.KeyDown += MainWindow_KeyDown; 

    } 

    private void MainWindow_KeyDown(object sender, KeyEventArgs e){ 
     if (e.Key.Equals(Key.Return)) { 
      socketThread.Start(); 
     } 
    } 

    public void refreshGUI(byte[]content) { 
     Action EmptyDelegate = delegate() { }; 
     BitmapSource source = BitmapSource.Create(1920, 1080, 72, 72, PixelFormats.Bgra32, BitmapPalettes.Gray256, content, 1920 * 4); 
     videoView.Source = source; 

     /*interrupt the socket-Loop to update GUI=> that is the current method without multithreading*/ 
     //this.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate); 

    } 


} 

SocketHandler

namespace Subscriber_WPF{ 

class SocketHandler{ 

    private int port; 
    private string publisherID; 
    private MainWindow window; 
    private static ZContext context; 
    private static ZSocket subscriber; 

    public SocketHandler(int port, string publisherID, MainWindow window) { 
     this.port = port; 
     this.publisherID = publisherID; 
     this.window = window; 
     this.initializeZMQSocket(this.port, this.publisherID); 
    } 

    private void initializeZMQSocket(int port, String publishID){ 
     context = new ZContext(); 
     subscriber = new ZSocket(context, ZSocketType.SUB); 
     /*initialize sockets*/ 
     subscriber.Connect("tcp://127.0.0.1:" + port); 
     subscriber.Subscribe(publishID); 
     Console.WriteLine("subscriber is ready!"); 
    } 


    public void runSocketRoutine(){ 
     Console.WriteLine("Waiting for Messages."); 

     while (true) 
     { 
      byte[] content = new byte[8294400]; 

      using (ZMessage message = subscriber.ReceiveMessage()) 
      { 
       Console.WriteLine("Message received!"); 
       string pubID = message[0].ReadString(); 
       /**/ 
       if (pubID.Equals(publisherID)) 
       { 

        content = message[1].Read(); 
        Console.WriteLine("size of content: " + message[1].Length); 
        window.refreshGUI(content); 
       } 

      } 
     } 

    } 


} 

Если кто-то имеет представление о том, как остановить, что затягивание дисплея или как я мог легко справиться с этой темой-вопросом, который я был бы очень благодарен!

Многие приветствия!

+1

Я думаю, вы пытаетесь обновить пользовательский интерфейс из другого потока, кроме MainThread = UIThread. Вы должны использовать 'Dispatcher.Invoke'http: //stackoverflow.com/questions/4253088/updating-gui-wpf-using-a-different-thread – Mat

+0

Возможный дубликат [Обновление GUI (WPF) с использованием другого потока] (http://stackoverflow.com/questions/4253088/updating-gui-wpf-using-a-different-thread) – Mat

+3

Итак, вы регулярно обновляете растровое изображение 1920 x 1080 для отображения и задаетесь вопросом о проблемах с производительностью? Возможно, вы должны найти другой способ представить свои визуальные данные. – grek40

ответ

2

Я сделал аналогичную вещь в прошлом, используя отличный RX framework. Ваша подпрограмма запуска запуска становится и IObservable, где T - тип, который вы возвращаете, в вашем случае byte []. Затем вы можете подписаться на этот поток в потоке пользовательского интерфейса. Используя структуру RX, вы также можете делать классные вещи, такие как ограничение скорости, поэтому, если ваша программа выплевывает множество «записей», вы можете ограничить это до 1 раза.

+0

Это не решит проблему перерисовки. Это сделает перерисовку более гладкой, но она все равно займет много CPU. –

+1

Правда, он все равно будет запрашивать много CPU, но по скорости, ограничивающей подписку, вы можете найти хороший компромисс между использованием ЦП и скоростью визуальной перерисовки. –

+0

@HenkHolterman извините, когда вы работали с системами ГИС почти в реальном времени, вы познакомиться со всеми проблемами, связанными с конкретными реализациями, такими как жесткие неконтролируемые циклы, перерисовка, мерцание и т. д. –