C#在线程之间轻松传递数据
我目前正在从事一个项目,在这个项目中,我以bytearray的形式接收帧并在GUI(WPF)上显示它们。现在我对性能不满意,因为帧显示延迟了。 因此,我考虑了多线程处理,以便套接字和GUI彼此独立工作。但是,如果我尝试在一个单独的线程中运行socketRoutine,我会得到一个错误,即一个线程无法访问另一个线程的ressource 我不知道这是什么意思。我猜要么是我传递给GUI的bytearray,要么是必须访问的GUI组件 这是我现在的代码C#在线程之间轻松传递数据,c#,wpf,zeromq,C#,Wpf,Zeromq,我目前正在从事一个项目,在这个项目中,我以bytearray的形式接收帧并在GUI(WPF)上显示它们。现在我对性能不满意,因为帧显示延迟了。 因此,我考虑了多线程处理,以便套接字和GUI彼此独立工作。但是,如果我尝试在一个单独的线程中运行socketRoutine,我会得到一个错误,即一个线程无法访问另一个线程的ressource 我不知道这是什么意思。我猜要么是我传递给GUI的bytearray,要么是必须访问的GUI组件 这是我现在的代码 namespace Subscriber_WPF{
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);
}
}
如果有人对如何停止延迟显示或如何轻松处理线程问题有想法,我将非常感激
大家好 我过去也曾用优秀的软件做过类似的事情。您的run套接字例程变为可观察,其中T是您返回的类型,在您的情况下为字节[]。然后,您可以在UI线程上订阅此流。使用RX框架,你还可以做一些很酷的事情,比如速率限制,因此如果你的例程抛出大量的“记录”,你可以将其限制为每个时间跨度1条。我过去也使用优秀的RX框架做过类似的事情。您的run套接字例程变为可观察,其中T是您返回的类型,在您的情况下为字节[]。然后,您可以在UI线程上订阅此流。使用RX框架,您还可以做一些很酷的事情,比如速率限制,因此如果您的例程抛出大量“记录”,您可以将其限制为每个时间间隔1条。我猜您可能会尝试从MainThread=UIThread以外的其他线程更新UI。您必须使用
Dispatcher.Invoke
的可能副本,以便定期重新创建1920 x 1080位图以显示并了解性能问题?也许你应该找到一种不同的方式来显示你的可视数据。也许在创建位图源代码之后,在将其推送到显示线程之前,只需.Freeze()
你的位图源代码就足够了。现在不能测试。@grek40-现在已经是2017年了。在现代PC上每秒创建少量2MPx图片应该不太难。在手机上可能有点太难。我猜您尝试从MainThread=UIThread以外的其他线程更新UI。您必须使用Dispatcher.Invoke
的可能副本,以便定期重新创建1920 x 1080位图以显示并了解性能问题?也许你应该找到一种不同的方式来显示你的可视数据。也许在创建位图源代码之后,在将其推送到显示线程之前,只需.Freeze()
你的位图源代码就足够了。现在不能测试。@grek40-现在已经是2017年了。在现代PC上每秒创建少量2MPx的图片应该不会太难。在手机上可能有点太多。这不会解决重绘问题。它将使重绘更平滑,但仍需要大量CPU。确实,它仍需要大量CPU,但通过限制订阅速率,您可以在CPU使用率和可视化重绘之间找到一个很好的折衷方案speed@HenkHolterman抱歉,当您使用近实时GIS系统时,您将了解与特定实现相关的所有问题,如紧密的不受控循环、重绘、闪烁等。例如抖动-即使重新绘制不需要任何成本,您也需要Rx来平滑帧。这是因为数据包会有随机延迟,UI线程可以在任何时候被抢占。这并不能解决重绘问题。它将使重绘更平滑,但仍需要大量CPU。确实,它仍需要大量CPU,但通过限制订阅速率,您可以在CPU使用率和可视化重绘之间找到一个很好的折衷方案speed@HenkHolterman抱歉,当您使用近实时GIS系统时,您将了解与特定实现相关的所有问题,如紧密的不受控循环、重绘、闪烁等。例如抖动-即使重新绘制不需要任何成本,您也需要Rx来平滑帧。这是因为数据包会有随机延迟,UI线程可以在任何时候被抢占。
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);
}
}
}
}
}