1

I would like to create a Thread in C# which will be counting frequency of sound at the microphone input of the computer. I am not asking about the FFT algorithm but just how to start a thread so I can modify A.hz field while Thread.hz is changing.

There will be only 1 Thread.

public class A()
{
    Thread t;
    int hz;  <-- i would like to change this when

    A()
    {
        starts Thread
        onchange t.hz modifies and dispays this.hz
    }        
}

class Thread
{
    int hz; <-- this changes

    void computeFrequency() <-- because of that method
    {
        changesHZField...
    }
}
Robert
  • 233
  • 3
  • 12
  • seems a duplicate of [this](http://stackoverflow.com/questions/7161413/thread-safe-properties-in-c-sharp) and other questions – Dmitry Ledentsov Nov 14 '12 at 15:53
  • I would not like to use any locks, just a primitive thread. – Robert Nov 14 '12 at 15:54
  • One thread-safe way would be to use [Rx](http://www.introtorx.com/Content/v1.0.10621.0/05_Filtering.html#Distinct). Your frequency could be a [sequence of ints](http://www.introtorx.com/Content/v1.0.10621.0/04_CreatingObservableSequences.html#ObservableCreate). A would subscribe to your measurement thread's events. – Dmitry Ledentsov Nov 14 '12 at 15:59
  • @Robert locks and threads aren't mutually exclusive. In fact, you'll usually use them together. The locks are needed so that you aren't modifying the same variables in different threads at the same time. Doing so generally causes...problems. – Servy Nov 15 '12 at 19:00
  • See an Rx solution [below](http://stackoverflow.com/a/13404121/847349) – Dmitry Ledentsov Nov 15 '12 at 19:31

3 Answers3

2

As promised, here's a solution using Rx:

using System;
using System.Reactive.Concurrency;
using System.Reactive.Linq;

namespace rxtest
{
    class FrequencyMeter
    {
        Random rand = new Random();
        public int Hz
        {
            get
            {
                return 60+rand.Next(3);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var obs = Observable.Generate<FrequencyMeter, int>(
                new FrequencyMeter(), //state
                x => !Console.KeyAvailable, // while no key is pressed
                x => x, // no change in the state
                x => x.Hz, // how to get the value
                x => TimeSpan.FromMilliseconds(250), //how often
                Scheduler.Default)
                .DistinctUntilChanged() //show only when changed
                ;

            using (IDisposable handle = obs.Subscribe(x => Console.WriteLine(x)))
            {
                var ticks = Observable.Interval(TimeSpan.FromSeconds(1)).Subscribe(x=>Console.WriteLine("tick")); //an example only
                Console.WriteLine("Interrupt with a keypress");
                Console.ReadKey();
            }
        }
    }
}

Delivering values asynchronously:

Interrupt with a keypress
60
61
tick
62
60
tick
61
60
tick
62
61
tick
62
60
tick
Dmitry Ledentsov
  • 3,620
  • 18
  • 28
  • 1
    Great solution, though I don't really like Generate if you can avoid it as there are too many parameters. A combination of Observable.Interval, Select and TakeWhile can do the same thing and is more fluent. – bradgonesurfing Nov 17 '12 at 14:17
  • Thank you for your comments, bradgonesurfing! I'd also like to make a little less verbose of that query, however, I haven't found a way to capture a single `Frequencymeter`. In [this](http://pastebin.com/dcbZtnGc) version the FrequencyMeter is created on each value from Interval. Do you have a certain solution in mind? – Dmitry Ledentsov Nov 17 '12 at 17:55
  • Well, perhaps, that's a dumb question, just capturing from outside the expression [would be easier](http://pastebin.com/Ru3hTs2c). The question is, whether Rx would care for thread safety of that instance – Dmitry Ledentsov Nov 17 '12 at 18:10
  • Your frequency meter class us just a stand in for polling some object for the real data. You would have to take care in the appropriate way for thread safety when polling a value that changes on another thread. – bradgonesurfing Nov 18 '12 at 05:56
1

You won't have to do anything special - multiple threads will be able to access your hz field. You'll need to consider synchronization issues (http://msdn.microsoft.com/en-us/library/ms173179.aspx)

When you have multiple threads reading/writing the same variable there are all sorts of problems. The easiest thing is probably to follow the link and copy their locking approach.

Rob P.
  • 14,921
  • 14
  • 73
  • 109
  • @Robert - I'm afraid I don't understand. When your application runs - you begin with one thread. You wouldn't need to create a new thread. Your sample code shows '//Starts thread' - if your code starts a thread; you have two threads - the original thread that started a thread and the new threat. – Rob P. Nov 14 '12 at 18:36
0
public class A()
{
    Thread t;
    int hz;

    A()
    {
        //starts Thread
    }

    internal void Signal(int hz){
        //modifies and dispays this.hz
    }

}

Now the Thread class can call the method Signal each time his property is set. To reference the A class instance, you can either pass it to the Thread class constructor and store a reference as private variable, or declare A itself as static; this depends on your overall architecture.

class MyThread : Thread
{
    int _hz;
    A _instance;

    public void MyThread(A inst){
        _instance = inst;
    }

    void computeFrequency()
    {
        //changesHZField...
        _instance.Signal(_hz);
    }
}

Finally, you might need to enable cross thread operations, depending on what you're doing in A class and MyThread class

LittleSweetSeas
  • 6,786
  • 2
  • 21
  • 26