【问题标题】:C# Passing data between Threads, easilyC#在线程之间传递数据,很容易
【发布时间】:2017-07-01 13:04:23
【问题描述】:

我目前正在从事一个项目,我将帧作为字节数组接收并在 GUI (WPF) 上显示它们。现在我对性能不满意,因为帧显示延迟。 所以我想到了做多线程,让socket和GUI彼此独立工作。但是,如果我尝试在单独的线程中运行 socketRoutine,我会收到一个错误,即一个线程无法访问另一个线程的资源。

我不确定是指哪个资源。我猜它要么是传递给 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);

    }


}

套接字处理程序

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

            }
        }

    }


}

如果有人知道如何停止延迟显示或如何轻松处理该线程问题,我将不胜感激!

许多问候!

【问题讨论】:

  • 我猜你尝试从 MainThread=UIThread 之外的另一个线程更新 UI。你必须使用Dispatcher.Invokestackoverflow.com/questions/4253088/…
  • 所以您定期重新创建一个 1920 x 1080 位图来显示并想知道性能问题?也许您应该找到一种不同的方式来呈现您的视觉数据。
  • 也许在创建之后并将其推送到显示线程之前.Freeze() 您的位图源就足够了。目前无法测试。
  • @grek40 - 现在是 2017 年。在现代 PC 上,每秒创建少量 2MPx 图片应该不会太难。在手机上可能有点太多了。

标签: c# wpf zeromq


【解决方案1】:

我过去曾使用出色的RX framework 做过类似的事情。您的运行套接字例程变为 IObservable,其中 T 是您返回的类型,在您的情况下为 byte[]。然后,您可以在 UI 线程上订阅此流。使用 RX 框架,您还可以做一些很酷的事情,例如速率限制,因此如果您的例程吐出大量“记录”,您可以将其限制为每个时间跨度 1 个。

【讨论】:

  • 这不会解决重绘问题。它会使重绘更顺畅,但仍会占用大量 CPU。
  • 没错,它仍然会要求大量 CPU,但通过限制订阅的速率,您可以在 CPU 使用率和视觉重绘速度之间找到一个很好的折衷方案
  • @HenkHolterman 抱歉,当您使用近实时 GIS 系统时,您会了解与特定实现相关的所有问题,例如紧密不受控制的循环、重绘、闪烁等。跨度>
  • 例如抖动 - 即使重新绘制不花费任何成本,您也需要 Rx 来平滑帧。这是因为数据包会有随机延迟并且 UI 线程可以在任何时候被抢占。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-18
  • 1970-01-01
  • 2014-10-12
  • 1970-01-01
  • 2015-04-22
  • 1970-01-01
  • 2021-08-17
相关资源
最近更新 更多