How can I mix the output of two different threads

2019-09-21 12:23发布

问题:

I have an application in C# which generates a series of images in the form of movie clip, which contains two methods. Each method generates a series of images (frames per second) which will display to my outputs (PictureBox_1 and PictureBox_2 accordingly).

My question is how can I mix this these series of images from two methods with each other randomly and instead of playing each thread separately I run the third thread which is the randomly mixing of two other threads?

For example the output are as follow:

Thread one: bmp1, bmp1, bmp1, …

Thread two: bmp2, bmp2, bmp2, …

Thread three; bmp1, bmp1, bmp2, bmp1, bmp2, bmp2, bmp2, bmp1, …

回答1:

The obvious solution would be to push generated images from both threads into a central Queue which is read by the third thread.

To notify the third thread about new pushed images you can use AutoResetEvent.


OK a quick example for you.

  class Program
  {
    static ConcurrentQueue<int> _centralQueue = new ConcurrentQueue<int>();
    static AutoResetEvent _signaller = new AutoResetEvent(false);

    static void Main(string[] args)
    {
      Task.Factory.StartNew(() => Producer1Thread());
      Task.Factory.StartNew(() => Producer2Thread());

      var neverEndingConsumer = Task.Factory.StartNew(() => ConsumerThread());
      neverEndingConsumer.Wait();
    }

    static void Producer1Thread()
    {
      for (int i=2000; i<3000; i++)
      {
        _centralQueue.Enqueue(i);
        _signaller.Set();          
        Thread.Sleep(8);
      }
    }

    static void Producer2Thread()
    {
      for (int i = 0; i < 1000; i++)
      {
        _centralQueue.Enqueue(i);
        _signaller.Set();
        Thread.Sleep(10);
      }
    }

    static void ConsumerThread()
    {
      while (true)
      {
        if (_centralQueue.IsEmpty)
        {
          _signaller.WaitOne();
        }
        int number;
        if (_centralQueue.TryDequeue(out number))
        {
          Console.WriteLine(number);
        }        
      }
    }
  }

First two threads produce numbers, one thread range 1-1000 other in 2000-3000. Third thread reads the produced results.

Ofcourse instead of int you would use your Image class.

Please note that the above code does neverEndingConsumer.Wait(); only for testing purposes. You don't want this in your code as it blocks forever.

Another hint: If you access the picturebox from the consumer thread don't forget to use Invoke to marshal the UI access to the GUI thread.



回答2:

You may generate yout images with a ThreadPool WorkerThread. The sequence you feed in the ThreadPool-Thread must not the same as they processed.

This seems a bit randomly...

Not tested or compiled, is just Pseudo-Code:

QueueUserWorkItem(()=>
{
    // code that generates the image
    var img = GenerateImage();
    // set image to PictureBox via SynchronizationContext of the UI-Thread
    formSyncContext.Send(()=> pb.Image = img);
}


标签: c# image random