0
Answer

Dispatcher causing problems

David

David

15y
3.3k
1
I have been trying to update a canvas containing a polyline from a non-UI thread.  I have read that in order to do so you have to use the "Dispatcher".

So, after reading all over the internet about the dispatcher, I tried it out, but I still get the same exception: I can't access the objects because the thread doesn't own them.

Here is my XAML:

<Window x:Class="FrequencyAnalysis.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="500" Width="640">
    <Grid Background="LightGray">
       
        <Button Content="Play Audio" Height="30" Width="100" Click="Button_Click"
                HorizontalAlignment="Left" VerticalAlignment="Top"
                Margin="5, 5, 0, 0"></Button>
       
        <Canvas Name="GraphingCanvas" HorizontalAlignment="Center" VerticalAlignment="Center"
                Width="500" Height="350" Background="White">
            <Polyline Name="poly_line" Stroke="Red" StrokeThickness="2"></Polyline>
        </Canvas>
       
    </Grid>
</Window>

And here is my code:

namespace FrequencyAnalysis 
    public partial class Window1 : Window 
    { 
        Player MyAudioPlayer; 
        XAudio2 audio_device; 
        MasteringVoice mastering_voice; 
        SourceVoice source_voice; 
        WaveFormat wave_format; 
        AudioBuffer audio_buffer; 
 
        public Window1() 
        { 
            InitializeComponent(); 
            MyAudioPlayer = new Player(); 
            audio_device = new XAudio2(); 
            mastering_voice = new MasteringVoice(audio_device); 
            source_voice = null
            wave_format = null
        } 
 
        private void Button_Click(object sender, RoutedEventArgs e) 
        { 
            Thread other_thread = new Thread(new ThreadStart(LoopCycle)); 
            other_thread.Start(); 
        } 
 
        delegate void UpdateTheUI(PointCollection point_collection); 
 
        private void DrawGraph(float[] data) 
        { 
            PointCollection point_collection = new PointCollection(); 
             
            for (int x = 0; x < data.Length; x++) 
            { 
                point_collection.Add(new Point(data[x], x)); 
            } 
 
            //The error happens here!!!!
            GraphingCanvas.Dispatcher.BeginInvoke((UpdateTheUI)delegate(PointCollection points) 
            { 
                poly_line.Points = points
            }, System.Windows.Threading.DispatcherPriority.Normal, point_collection ); 
        } 
 
        private void LoopCycle() 
        { 
            string FileName = "MusicSurround.wav"
 
            audio_buffer = MyAudioPlayer.OpenFile(ref audio_device, ref source_voice, ref wave_format, FileName); 
            MyAudioPlayer.PlayAudio(ref source_voice, ref audio_buffer); 
 
            // loop until the sound is done playing 
            while (source_voice.State.BuffersQueued > 0) 
            { 
                int sample_count = wave_format.SamplesPerSecond / 100; 
                sample_count = NearestPowerOfTwo(sample_count); 
 
                Complex[] freq_data = MyAudioPlayer.GetCurrentFrequencies(ref source_voice, ref audio_buffer, 
                                                                    ref wave_format, sample_count); 
                float[] powerspec = FindPowerSpectrum(freq_data); 
 
                DrawGraph(powerspec); 
 
                Thread.Sleep(10); 
            } 
 
            audio_buffer.Dispose(); 
            source_voice.Dispose(); 
        } 
    } 

The error clearly happens inside the DrawGraph() function when I try to assign the new point collection to the polyline.  I know that because everything runs well when that line is commented out.

In case you are having trouble following the code, the functions are:

Button_Click( )
DrawGraph( )
LoopCycle( )

When the button is clicked, it starts up another thread, and that thread executes the LoopCycle() function which plays an audio file.

As the audio file plays, my objective is to output the current frequencies being played from the audio file in real time (using the FFT).  So I calculate all that jazz using the FFT, and then I want to display my results (keep in mind this will be happening several times every second).

Thus I have a very primitive graphing mechanism right now: a canvas and a polyline.  The polyline is composed of all the points in the resulting data returned from the FFT algorithm.  So I call DrawGraph() which is supposed to hand that set of points to the polyline object, and then the polyline object should update itself on the canvas.

Thanks for any help!