在任务/线程上运行小操作
本文关键字:运行 操作 线程 任务 | 更新日期: 2023-09-27 18:10:51
我正在录制IP电话的音频,用c#编写。
我有一个方法,为我捕获的每个数据包运行(大量数据包)。该方法用有效负载数据填充缓冲区。
public void HandlePayload(byte[] payload, IpV4Address dstIp)
{
count++;
// packet from source
if (dstIp == _dstIp)
{
AddPayloadToArray(MuLawDecoder.MuLawDecode(payload), ArrayType.SRC_PCM);
// Task.Run(() =>AddPayloadToArray(MuLawDecoder.MuLawDecode(payload), ArrayType.SRC_PCM));
}
// packet from destination
if (dstIp == _srcIp)
{
AddPayloadToArray(MuLawDecoder.MuLawDecode(payload), ArrayType.DST_PCM);
// Task.Run(() =>AddPayloadToArray(MuLawDecoder.MuLawDecode(payload), ArrayType.DST_PCM));
}
}
EDIT: The Play Method
public void PlayCall(SkinnyCall call)
{
Waveout.Play();
byte[] mixedBuffer = new byte[320];
while (_playerIndex < call.AudioArrays[(int)ArrayType.Pcm].Length)
{
if (_state == PlayerState.Paused || _state == PlayerState.Stopped)
// call either paused or stopped
break;
for (int i = 0; i < 320; i++)
{
mixedBuffer[i] = (byte)(call.AudioArrays[(int)ArrayType.Pcm][_playerIndex + i];
}
_playerIndex += 320;
Thread.Sleep(20);
AddSamples(mixedBuffer);
ClearByteArray(ref mixedBuffer);
}
if (_playerIndex == call.AudioArrays[(int)ArrayType.Pcm])
{
// call has finished and Playback is over
StopCall(call);
PlaybackEnded();
}
}
我需要一种方法来运行它在不同的线程/任务,因为当我正常运行它(在同一线程上)有延迟一段时间后,它变得更大。
每次运行Task.run时,我都试图使用它,但它总是出现问题。
基本上,寻找一种方法,使一个线程/任务的工作将只运行这些操作,而不运行其他操作,而不必每次都新建线程。
,并且每次都能传递参数给它。
任何想法吗?我已经纠结了一段时间了…
谢谢!
正确的方法是创建第二个线程并通过ConcurrentQueue传递数据,您可以查看msdn示例。
但是这需要大量的手工多线程工作。我个人建议你看看TPL数据流,这是一个非常棒的框架,对于这样的任务
下面是一个如何创建和使用TPL数据流的快速示例// Create bufferBlock for store
BufferBlock<byte[]> _inputBufferBytes = new BufferBlock<byte[]>();
// Create action block for job
ActionBlock<byte[]> _inputBufferParcer = new ActionBlock<byte[]>(bytes => ProcessInputBuffer(bytes));
// Link one block to another
// from [_inputBufferBytes] to [_inputBufferParcer]
_inputBufferBytes.LinkTo(_inputBufferParcer);
...
// add new bytes to buffer
_inputBufferBytes.Post(buffer);
你可以自由地从任何线程发布数据到BufferBlock,它们将在ActionBlock中以先进先出的方式异步解析。有几种类型的块,如TransformBlock<in,out>
或BatchBlock
,它们生成数据数组。我建议您阅读手册,TPL Dataflow可能相当强大。
您可以使用生产者-消费者队列来同步两个线程之间的工作。特别是BlockingCollection
使这样的代码变得轻而易举。
然而,你更有可能遇到一个不同的问题——你应该能够在一个线程上实时处理数据。确保性能问题确实在您认为的地方,测量代码的每个部分所损失的时间。使用Task.Run
不是最好的主意,但它会工作(并且它实际上并不创建新线程-它重用线程池中的线程)。
根据您的内存使用模式,您甚至可能遇到垃圾收集器的问题。CLRProfiler
将帮助你确定这一点,你可能还想调查你是如何使用byte[]
缓冲区,你正在传递-如果你实际上没有复制它的任何地方,只是传递一个引用到原始缓冲区,多线程将意味着你会得到你的数据重写之前,它有机会被处理。
黄金法则是——衡量。概要文件。找出为什么你被延误了。Task
基础架构实际上非常快,所以它不太可能是瓶颈。猜测不会让你走得太远,特别是如果你对这类问题没有太多经验的话。