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并播放,该如何做呢?
{
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并播放,该如何做呢?
void findAndPlay_DoWork(object sender, DoWorkEventArgs e)
{
if (new BackgroundWorker().Open(@"E:\mp3\我从草原来.mp3")) mp.Play();
}
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会错呢?
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字节控制左声道。
}
}
}
}
也就是说你要把mciSendString放在UI线程来做。
实际上我说他不行的时候用的就是本地的MP3文件,但注释掉的却行。最初,我写的是一个封装好的类,用backGroundWork自动搜索并播放,发现不行后,才又做的上面的模型,谁知仍然无解。
{
if (mp.Open(@"E:\mp3\我从草原来.mp3")) mp.Play();
});
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();
谢谢逍遥!如果能在 BackgroundWorker 中使用最好啦(上面的只是个模型),我用了[STAThread]为何不行呢?
[STAThread]
void findAndPlay_DoWork(object sender, DoWorkEventArgs e)
{
if (mp.Open(@"E:\mp3\我从草原来.mp3")) mp.Play();
}
是描述线程的,不是描述回调方法的。
可能有“在 BackgroundWorker 中使用”的方案吗?
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.