This project has moved and is read-only. For the latest updates, please go here.

Error with Backgroundworker and MIDI

Jun 17, 2011 at 12:51 AM
Edited Jun 17, 2011 at 1:21 AM

Please can tellme and if possible correct my code for make this work?
basically i need run MIDI in background using backgroundworker.


Im not lazy, just confused with this.

I open this new discussion, for not make the other ultra large adn due the other is mixed with MIDI, you know.

NAudio.MmException was unhandled by user code
Message=AlreadyAllocated calling midiOutOpen
Source=NAudio
StackTrace:
       at NAudio.MmException.Try(MmResult result, String function)
       at NAudio.Midi.MidiOut..ctor(Int32 deviceNo)
       at MTHR_Bug.MainWindow.RunInBackground(Object sender, DoWorkEventArgs e) in 
C:\Users\Groboto\Desktop\MTHR-bug - Copy\MTHR-Bug\MTHR-Bug\MainWindow.xaml.cs:line 62 at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e) at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument) InnerException:

Here the code, i use timer at 1ms for simulate multiple faster event fired.
At the end, of the code, i show more code, making the same, but outside of backgroundworker, with 0 error or problem!
Why, with backgroudn worker happen this and without no?



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;
using System.Windows.Threading;
using NAudio.Midi;


namespace MTHR_Bug
{

    public partial class MainWindow : Window
    {

     
       int MIDIDEVICE = 1;
     

        public MainWindow()
        {
            InitializeComponent();
        }


        System.ComponentModel.BackgroundWorker backgroundWorker;

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
       
            DispatcherTimer timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(1);
            timer.Tick += new EventHandler(timer_run);
            timer.Start();

        }



        private void timer_run(Object sender, EventArgs args)
        {
            backgroundWorker = new System.ComponentModel.BackgroundWorker();
            backgroundWorker.WorkerSupportsCancellation = true;
            backgroundWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(RunInBackground);
            backgroundWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(RunInBackgroundComplete);
            backgroundWorker.RunWorkerAsync();
        }


            private void RunInBackground(object sender, System.ComponentModel.DoWorkEventArgs e)
            {
                MidiOut midiOut = new MidiOut(MIDIDEVICE);
                midiOut.Send(MidiMessage.StartNote(1, 1, 1).RawData);
                midiOut.Dispose();
            
            }

            private void RunInBackgroundComplete(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
            {
                backgroundWorker.Dispose();
            }

    }
}


-------------------------------------------------------------------------------------------------------

This is the same, but without backgroundworker! 0 problem!


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;
using System.Windows.Threading;
using NAudio.Midi;
namespace MTHR_Bug
{

    public partial class MainWindow : Window
    {

       int MIDIDEVICE = 1;
      
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {        
            DispatcherTimer timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(1);
            timer.Tick += new EventHandler(timer_run);
            timer.Start();
        }

        private void timer_run(Object sender, EventArgs args)
        {
                MidiOut midiOut = new MidiOut(MIDIDEVICE);
                midiOut.Send(MidiMessage.StartNote(1, 1, 1).RawData);
                midiOut.Dispose();
        }

    }
}
Jun 17, 2011 at 7:13 AM

First, you need to stop opening and closing MIDI out all the time. Open it once when your app starts. Close it when your app ends:

    public partial class MainWindow : Window
    {

       int MIDIDEVICE = 1;
       MidiOut midiOut;
      
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {        
            this.midiOut = new MidiOut(MIDIDEVICE);
 
            DispatcherTimer timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(1);
            timer.Tick += new EventHandler(timer_run);
            timer.Start();

            this.Closed += (o,s) => midiOut.Dispose();
        }

        private void timer_run(Object sender, EventArgs args)
        {
                midiOut.Send(MidiMessage.StartNote(1, 1, 1).RawData);
        }

    }
}

Second, the reason your app is falling over is because you are creating MIDI events faster than you can send them. You end up with multiple threads trying to send MIDI at the same time. If you really want to use a background thread, create just one background thead and let that send events in a loop / read from a queue.

Mark

Jun 17, 2011 at 6:53 PM

Mark you are 100% right.
No bug just my fault!!
Thankyou so much !

Aug 2, 2012 at 12:10 PM

mark can post some example of how do this "If you really want to use a background thread, create just one background thread and let that send events in a loop / read from a queue"

I need find way to send midi in faster way, without thread affect all application.
Right now send midi act like a bottleneck, specially affecting the UI thread making all work slow when send midi.
Bets regards!