Search code examples
c#multithreadingtaskdelay

Running small Operation on task/thread


I am recording audio from IP Phones, writing in c#.

I have a method that runs for each packet the I capture (A LOT of packets). the method fills the buffer with the payload data.

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

I need a way to run it on a different thread/task because when I run it normally (on the same thread) there is delay after a while and its getting bigger.

I tried to use Task.run each time I run it, but it did problems.

Basically, looking for a way to have one thread/task that its job will be to run only those operations, and nothing else, without having to do New Thread everytime.

and to be able to pass parameters to it every time.

any thoughts? been struggling with this for a while..

thanks!


Solution

  • You can use a producer-consumer queue to synchronize work between two threads. BlockingCollection in particular makes code like this a breeze.

    However, you're more likely running into a different issue - you should be able to process the data in real-time on one thread just fine. Make sure the performance problem actually is where you think it is, measure the time you lose in each part of your code. Using Task.Run is not the best idea, but it would work (and it does not actually create new threads - it reuses threads from the thread-pool).

    Depending on your memory usage pattern, you might even be running into issues with the garbage collector. CLRProfiler will help you determine that, and you might also want to investigate how you're using the byte[] buffers you're passing around - if you're not actually copying it anywhere and are only passing a reference to the original buffer, multi-threading will mean you'll get your data rewritten before it has a chance to be processed.

    The golden rule is - measure. Profile. Find out why you're getting delayed. The Task infrastructure is actually incredibly fast, so it's quite unlikely that's the bottleneck. Guessing won't get you far, especially if you don't actually have much experience with this kind of problem.