C#多线程处理大量不同类型的实时数据

muyiliu 2020-04-27 09:04:12
向各位大神请教一个多线程的问题。UDP通信中,数据量很大,达到每秒几兆的量。现在我开了A、B两个端口接收不同的数据。线程A接收端口A传输的频谱数据,线程B接收端口B传输的语音数据。在线程A中有耗时的画图程序,一次耗时400多毫秒。现在的现象就是,如果运行画图程序,实时语音就会断断续续,感觉是丢包了。如果不运行画图程序,实时语音就很连续。请问大神怎么解决这个问题。我用的语言是C#,我对线程这块只懂皮毛,不够深入。请大神支个招,谢谢。解决必有回报
...全文
998 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
你的问题在于接收数据那里,不要起新线程处理数据,把他放到一个队列里处理
number007cool 2020-04-28
  • 打赏
  • 举报
回复
引用 3 楼 wanghui0380 的回复:
不知道具体实现,作为程序员我们只能黑箱猜测,按照可能解决问题的顺序排一下 1检查UI操作部分,虽然你说分线程了,不过总归要操作UI,那么有可能会做同步invoke,建议异步begininvoke 2建议把大量IO和大量计算部分单独运行,同时进行限流动作。不要一次并发太多,避免上个绘制还未完成,下个绘制就开始的情况 3 如果一定是并发,建议离屏绘制 4 根据经验音频的200ms空白大概相当与人类正常语速的断句停顿时间,所以建议频率数据(我不知道你到底是频率还是原始pcm)重新window动态采样或抽样,保证显示速度。 总体上可以按这个顺序解决,不过我们需要你实际测试。看到底是那部分问题,是IO的征用,还是cpu的争用,又或是UI更新产生阻塞
请教下同步invoke和异步invoke有什么区别
muyiliu 2020-04-28
  • 打赏
  • 举报
回复
引用 5 楼 wanghui0380 的回复:
从项目上说udp不丢包,不串时序比较难 能否修改一下项目架构,直接用rstp协议接流。这样就算先临时对付直接用ffmepg播放音频都可以完成(优先完成,即使ffmepg不理想,后面再改自己直接接rstp也可以做)
架构改不了了,这个是总体已经定下来的。 我试过,如果把频谱和语音做成两个exe,语音就很正常互不影响。但是在一个进程里,感觉就像是楼上大神说的可能是UI产生阻塞
muyiliu 2020-04-28
  • 打赏
  • 举报
回复
引用 3 楼 wanghui0380 的回复:
不知道具体实现,作为程序员我们只能黑箱猜测,按照可能解决问题的顺序排一下 1检查UI操作部分,虽然你说分线程了,不过总归要操作UI,那么有可能会做同步invoke,建议异步begininvoke 2建议把大量IO和大量计算部分单独运行,同时进行限流动作。不要一次并发太多,避免上个绘制还未完成,下个绘制就开始的情况 3 如果一定是并发,建议离屏绘制 4 根据经验音频的200ms空白大概相当与人类正常语速的断句停顿时间,所以建议频率数据(我不知道你到底是频率还是原始pcm)重新window动态采样或抽样,保证显示速度。 总体上可以按这个顺序解决,不过我们需要你实际测试。看到底是那部分问题,是IO的征用,还是cpu的争用,又或是UI更新产生阻塞
//线程A用于接收频谱数据 m_ReceiveLister_A = new Thread(new ThreadStart(ReciveListerA)); m_ReceiveLister_A.Start(); //线程B用于接收语音数据 语音数据为PCM m_ReceiveLister_B = new Thread(new ThreadStart(m_ReceiveLister_B)); m_ReceiveLister_B.Start(); //线程A接收函数,接收频谱数据 ReciveListerA() { //读取端口A的数据 byte[] bytes = m_UdpClient.Receive(ref m_RemoteIPEndPoint); Task task =new Task(()=>Draw(data)) task.Start(); } //画图函数 Draw(byte[] data) { this.BeginInvoke( new Action()=> { //画频谱图 //画瀑布图 //两个画图操作耗时400ms })); } //线程B接收函数,接收频谱数据 ReciveListerB() { //读取端口A的数据 byte[] bytes = m_UdpClient.Receive(ref m_RemoteIPEndPoint); Task task =new Task(()=>Play(data)) task.Start(); } //播放语音PCM数据 Play(byte[] data) { this.BeginInvoke( new Action()=> { //播放 })); }
wanghui0380 2020-04-28
  • 打赏
  • 举报
回复
从项目上说udp不丢包,不串时序比较难 能否修改一下项目架构,直接用rstp协议接流。这样就算先临时对付直接用ffmepg播放音频都可以完成(优先完成,即使ffmepg不理想,后面再改自己直接接rstp也可以做)
muyiliu 2020-04-28
  • 打赏
  • 举报
回复
最好看下具体的代码 1.数据接收和解析一定一定要分离,否则解析的过程就会直接影响到数据的接收。 推荐解析使用线程池的方式,当然还得看业务要求,如果有严格的时序关系,那线程池不一定可行。 2.如果频谱数据不是严格要求,不用展示全部的数据;采用抽样显示的方法, 因为屏幕显示的像素是有限个,超过了也没有太大的必要。 3.如果A与B接收没有关联,接收也可以考虑多进程来处理。[/quote] 数据接收和解析已经分开了。频谱数据要求不严格,少一包数据没关系。不过语音不一样,时序很重要,同样也不能丢包。A、B接收没有关系是两种不同的数据,请问下怎么用多进程来处理?可否写一段示例程序,谢谢了!
wanghui0380 2020-04-28
  • 打赏
  • 举报
回复
不知道具体实现,作为程序员我们只能黑箱猜测,按照可能解决问题的顺序排一下 1检查UI操作部分,虽然你说分线程了,不过总归要操作UI,那么有可能会做同步invoke,建议异步begininvoke 2建议把大量IO和大量计算部分单独运行,同时进行限流动作。不要一次并发太多,避免上个绘制还未完成,下个绘制就开始的情况 3 如果一定是并发,建议离屏绘制 4 根据经验音频的200ms空白大概相当与人类正常语速的断句停顿时间,所以建议频率数据(我不知道你到底是频率还是原始pcm)重新window动态采样或抽样,保证显示速度。 总体上可以按这个顺序解决,不过我们需要你实际测试。看到底是那部分问题,是IO的征用,还是cpu的争用,又或是UI更新产生阻塞
xian_wwq 2020-04-28
  • 打赏
  • 举报
回复
引用 楼主 muyiliu 的回复:
向各位大神请教一个多线程的问题。UDP通信中,数据量很大,达到每秒几兆的量。现在我开了A、B两个端口接收不同的数据。线程A接收端口A传输的频谱数据,线程B接收端口B传输的语音数据。在线程A中有耗时的画图程序,一次耗时400多毫秒。现在的现象就是,如果运行画图程序,实时语音就会断断续续,感觉是丢包了。如果不运行画图程序,实时语音就很连续。请问大神怎么解决这个问题。我用的语言是C#,我对线程这块只懂皮毛,不够深入。请大神支个招,谢谢。解决必有回报
最好看下具体的代码 1.数据接收和解析一定一定要分离,否则解析的过程就会直接影响到数据的接收。 推荐解析使用线程池的方式,当然还得看业务要求,如果有严格的时序关系,那线程池不一定可行。 2.如果频谱数据不是严格要求,不用展示全部的数据;采用抽样显示的方法, 因为屏幕显示的像素是有限个,超过了也没有太大的必要。 3.如果A与B接收没有关联,接收也可以考虑多进程来处理。
lindexi_gd 2020-04-28
  • 打赏
  • 举报
回复
可以开启消费模式,也就是一个接收端用于接收数据,然后开启多个线程处理接收的数据

我开源了异步多线程处理工具,放在 https://github.com/dotnet-campus/AsyncWorkerCollection

可以通过 AsyncQueue 来做这样的事情

创建一个全局静态的 AsyncQueue 属性,请将 Xx 替换为你的数据类型,可以传入数据类型的接口或基类

public static AsyncQueue<Xx> AsyncQueue {get;} = new AsyncQueue<Xx> ();

接收线程接收

// 接收数据代码
Xx 接收到的数据 = 接收数据代码();

AsyncQueue.Enqueue(接收到的数据);

在多个处理线程的代码

while(true)
{
var xx = await AsyncQueue.DequeueAsync();
// 处理 xx 数据
}
wanghui0380 2020-04-28
  • 打赏
  • 举报
回复
那就分成2个exe(其实java们经常这么做,你可以看到java经常调用FFmpeg去干活的) 至于数据部分,你可以单独封装,传初始化参数。也可以使用netmq通过管道传递。 先把项目做了,再去研究到底怎么回事。
muyiliu 2020-04-28
  • 打赏
  • 举报
回复
引用 9 楼 闭包客的回复:
在找解决办法之前先要定位问题出在哪里。 你看到的现象是,在运行画图程序的时候,实时语音就会断断续续。从你给出的信息来看,是不足以找出问题出在哪里的。 画图程序和实时语音是不是两个独立的工作单元?他们会不会互相影响? 如果是的话,那么就可能是资源出现了瓶颈。一般来说瓶颈会出现在带宽上面,也会出在 CPU 上面,也会出在内存和硬盘上面。在实时语音断断续续的时候,这些硬件的使用情况是怎么样的? 这些可能出现问题的地方,你都要去看一下,即使问题不出现在这里,也排除了一个可能性。很多时候都是使用这样的排除法去解决问题的。
就是定位问题所在。我测试了,把画频谱和播放语音写成独立的exe进程,这是语音就能正常运行。但是一个进程中,多个线程,语音就断断续续。
闭包客 2020-04-28
  • 打赏
  • 举报
回复
在找解决办法之前先要定位问题出在哪里。 你看到的现象是,在运行画图程序的时候,实时语音就会断断续续。从你给出的信息来看,是不足以找出问题出在哪里的。 画图程序和实时语音是不是两个独立的工作单元?他们会不会互相影响? 如果是的话,那么就可能是资源出现了瓶颈。一般来说瓶颈会出现在带宽上面,也会出在 CPU 上面,也会出在内存和硬盘上面。在实时语音断断续续的时候,这些硬件的使用情况是怎么样的? 这些可能出现问题的地方,你都要去看一下,即使问题不出现在这里,也排除了一个可能性。很多时候都是使用这样的排除法去解决问题的。

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧