namespace Mp3Player
{
    public partial class Form1 : Form
    {
        mciAudioPlay mp = new mciAudioPlay();
        BackgroundWorker findAndPlay = new BackgroundWorker();        public Form1()
        {
            InitializeComponent();
        }        private void Form1_Load(object sender, EventArgs e)
        {
            findAndPlay.DoWork += new DoWorkEventHandler(findAndPlay_DoWork);
            findAndPlay.RunWorkerAsync();
        }        void findAndPlay_DoWork(object sender, DoWorkEventArgs e)
        {
            if (mp.Open(@"E:\mp3\我从草原来.mp3")) mp.Play();
        }        //private void btnPlayMp3_Click(object sender, EventArgs e)
        //{
        //    if (mp.Open(@"e:\mp3\冲动的惩罚.mp3")) mp.Play();
        //}
    }
}上面的代码用来播放Mp3,mciAudioPlay是播放Mp3的类。被注释的代码是可以正常工作的但放在BackgroundWorker 中就老是出现266号错误,即:“指定的设备未打开,或不被MCI所识别。”,为什么会出现这样的情况呢?我确实想在 BackgroundWorker 中打开Mp3并播放,该如何做呢?

解决方案 »

  1.   

    改这样试试?
    void findAndPlay_DoWork(object sender, DoWorkEventArgs e)
    {
        if (new BackgroundWorker().Open(@"E:\mp3\我从草原来.mp3")) mp.Play();
    }
      

  2.   

    Open 是我在 mciAudioPlay 类中定义的方法啊!
      

  3.   


            public bool Open(string fileName)   // 打开一个要播放的文件
            {
                bool b = false;
                try
                {
                    if (Status != PlayStatus.NoPlayFile) Close();
                    errCode = mciSendString("open \"" + fileName + "\" alias NetMp3", buff, buff.Length, 0);
                    b = errCode == 0;
                }
                finally
                {
                    if (b) Name = fileName;
                    else Name = string.Empty;
                }
                return b;
            }
    关键是我不觉得我的代码有错啊!为什么在BackgroundWorker会错呢?
      

  4.   

    行,没问题:using System;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.IO;
    namespace Mp3Player
    {
        class mciAudioPlay
        {
            [DllImport("winmm.dll", EntryPoint = "mciSendString", CharSet = CharSet.Auto)]
            public static extern int mciSendString(string lpstrCommand, string lpstrReturnString, int uReturnLength, int hwndCallback);        [DllImport("winmm.dll", EntryPoint = "mciGetErrorString", CharSet = CharSet.Auto)]
            public static extern int mciGetErrorString(int errCode, string lpstrReturnString, int uReturnLength);        [DllImport("winmm.dll", EntryPoint = "waveOutSetVolume", CharSet = CharSet.Auto)]
            public static extern int waveOutSetVolume(uint deviceID, uint Volume);      //参数为uint          public enum PlayStatus              // 播放状态
            {
                Playing, Paused, Stopped, NoPlayFile
            }        private string Name = "";           // 存放播放的文件名
            private string buff = "................................................................................................................................";
            private int errCode;                // 执行mciSendString返回的错误码
            //private PlayStatus status = PlayStatus.NoPlayFile;
            public string Message               // 根据错误码返回错误信息字符串
            {
                get
                {
                    mciGetErrorString(errCode, buff, buff.Length);
                    int p = buff.IndexOf('\0');
                    return buff.Substring(0, p);
                }
            }        public bool Open(string fileName)   // 打开一个要播放的文件
            {
                bool b = false;
                try
                {
                    if (Status != PlayStatus.NoPlayFile) Close();
                    errCode = mciSendString("open \"" + fileName + "\" alias NetMp3", buff, buff.Length, 0);
                    b = errCode == 0;
                }
                finally
                {
                    if (b) Name = fileName;
                    else Name = string.Empty;
                }
                return b;
            }        public void Play()                  // 播放 - playing
            {
                errCode = mciSendString("play NetMp3", buff, buff.Length, 0);  // play NetMp3 repeat 循环播放
            }        public void Stop()                  // 停止 - stopped
            {
                Position = 0;                   // mciSendString("stop NetMp3", buff, buff.Length, 0);
            }        public void Pause()                 // 状态将变为 - paused
            {
                errCode = mciSendString("pause NetMp3", buff, buff.Length, 0);
            }        public void Continue()              // 状态将变为 - playing
            {
                errCode = mciSendString("resume NetMp3", buff, buff.Length, 0);
            }        public void Close()                 // 状态将变为 - 空
            {
                errCode = mciSendString("close NetMp3", buff, buff.Length, 0);
                //errCode = mciSendString("close all", buff, buff.Length, 0);
            }        public string FileName              // 播放的文件
            {
                get
                {
                    return Name;
                }
                set
                {
                    Open(value);
                }
            }        public PlayStatus Status            // 获取当前状态: playing / paused / stopped / 空
            {
                get
                {
                    if(string.IsNullOrEmpty(Name))return PlayStatus.NoPlayFile;
                    PlayStatus status;
                    errCode = mciSendString("status NetMp3 mode", buff, buff.Length, 0);
                    int p = buff.IndexOf('\0');
                    string s = buff.Substring(0, p);
                    switch (s)
                    {
                        case "playing": status = PlayStatus.Playing; break;
                        case "paused": status = PlayStatus.Paused; break;
                        default: status = PlayStatus.Stopped; break;
                    }
                    return status;
                }
            }
            public int Length                   // 歌曲总长度(毫秒)
            {
                get
                {
                    errCode = mciSendString("status NetMp3 length", buff, buff.Length, 0);
                    int p = buff.IndexOf('\0');
                    string s = buff.Substring(0, p);
                    if (string.IsNullOrEmpty(s)) return 0;
                    return int.Parse(s);
                }
            }        public int Position                 // 播放位置(毫秒)
            {
                get
                {
                    errCode = mciSendString("status NetMp3 position", buff, buff.Length, 0);
                    int p = buff.IndexOf('\0');
                    string s = buff.Substring(0, p);
                    if (string.IsNullOrEmpty(s)) return 0;
                    return int.Parse(s);
                }
                set
                {
                    errCode = mciSendString("seek NetMp3 to " + value, buff, buff.Length, 0);
                }
            }        public int Volume                   // 音量 0 ~ 1000
            {
                get
                {
                    errCode = mciSendString("status NetMp3 volume", buff, buff.Length, 0);
                    int p = buff.IndexOf('\0');
                    string s = buff.Substring(0, p);
                    if (string.IsNullOrEmpty(s)) return 0;
                    return int.Parse(s);
                }
                set
                {
                    errCode = mciSendString("setaudio NetMp3 volume to " + value, buff, buff.Length, 0);
                }
            }        public uint LeftRightVolume         // 分别控制左右声道的音量
            {
                set
                {
                    waveOutSetVolume(0, value);  // 0xffffffff,高2字节控制右声道,低2字节控制左声道。
                }
            }
        }
    }
      

  5.   

    其实我是搜索网络的Mp3音乐进行播放,有的网站的mp3在执行open 时会花费较长的时间而造成界面假死,所以希望将查找并播放的代吗放在BackgroundWorker中来进行。
      

  6.   

    如果没有记错的话,mciSendString需要一个消息泵(Message Loop)才能工作。
    也就是说你要把mciSendString放在UI线程来做。
      

  7.   


    实际上我说他不行的时候用的就是本地的MP3文件,但注释掉的却行。最初,我写的是一个封装好的类,用backGroundWork自动搜索并播放,发现不行后,才又做的上面的模型,谁知仍然无解。
      

  8.   

    如果这样,哪真是一个悲剧啦,比如UI界面上有MP3的播放列表,用户双击其一进行播放,半天没出来,又双击第2个,不用说,程序很快死掉。如何解决这样的问题呢?若不行,有无设置“ mciSendString的Open命令” 执行的时间长度限制,或者 能否及时强制结束BackgroundWorker线程的方法,当然,这里说的不是CancellationPending什么的标志检测。因为还没执行到检测的位置,程序已经死啦!
      

  9.   

    试了一下,只有STA的线程可以。你的Load事件中这样写试试。不用BackgroundWorkerThread t = new Thread((ThreadStart)delegate
        {
            if (mp.Open(@"E:\mp3\我从草原来.mp3")) mp.Play();
        });
    t.SetApartmentState(ApartmentState.STA);
    t.IsBackground = true;
    t.Start();
      

  10.   


    谢谢逍遥!如果能在 BackgroundWorker 中使用最好啦(上面的只是个模型),我用了[STAThread]为何不行呢?
            [STAThread]
            void findAndPlay_DoWork(object sender, DoWorkEventArgs e)
            {
                if (mp.Open(@"E:\mp3\我从草原来.mp3")) mp.Play();
            }
      

  11.   

    [STAThread]
    是描述线程的,不是描述回调方法的。
      

  12.   


    可能有“在 BackgroundWorker 中使用”的方案吗?
      

  13.   

    msdn的解释
    If you attempt to set the apartment to STA, then .NET will override you and set the apartment to MTA because the thread is a pool thread and cannot be devoted to accessing a single object. In this scenario we need to use the thread class to execute the asynchronous operation.