C# #:";调用线程无法访问此对象,因为其他线程拥有它";?

C# #:";调用线程无法访问此对象,因为其他线程拥有它";?,c#,multithreading,visual-studio,C#,Multithreading,Visual Studio,我知道其他用户问了这个问题,但我不知道如何解决我的问题。 下面是我的代码(对不起,可能太长了)。Visual Studio在sounds[i].Stop()行上说“调用线程无法访问此对象,因为它属于另一个线程”。为什么?如何解决这个问题?非常感谢 private Thread th = null; private void Form1_KeyDown(object sender, KeyPressEventArgs e) { foreach (PictureBox key in pane

我知道其他用户问了这个问题,但我不知道如何解决我的问题。 下面是我的代码(对不起,可能太长了)。Visual Studio在
sounds[i].Stop()行上说“调用线程无法访问此对象,因为它属于另一个线程”。为什么?如何解决这个问题?
非常感谢

private Thread th = null;
private void Form1_KeyDown(object sender, KeyPressEventArgs e)
{
    foreach (PictureBox key in panel.Controls)
    {
        string name = key.Name;
        string[] parts = name.Split('_');

        if (e.KeyChar.ToString() == parts[1])
        {
            th = new Thread(press);
            th.Start(new object[] { key, name });
        }
    }
}

private void Form1_KeyUp(object sender, KeyEventArgs e)
{
    foreach (PictureBox key in panel.Controls)
    {
        string name = key.Name;
        string[] parts = name.Split('_');

        if (Convert.ToChar(e.KeyValue).ToString().ToLower() == parts[1])
            leave(key, name);
    }
}

private void press(object data)
{
    object[] array = (object[])data;

    PictureBox pressedKey = (PictureBox)array[0];
    string name = (string)array[1];
    string[] parts = name.Split('_');

    [...] Other code

    play(parts[1].ToString());
}

private void leave(object sender, string name)
{
    PictureBox pressedKey = sender as PictureBox;
    string numero = pressedKey.Name;
    string[] parts = numero.Split('_');

    [...] Other code

    stopPlay(parts[1].ToString());
}

List<System.Windows.Media.MediaPlayer> sounds = new List<System.Windows.Media.MediaPlayer>();
private void play(string note)
{
    int i = 0;
    string url;
    bool diesis = false;
    var sound = new System.Windows.Media.MediaPlayer();
    while (!diesis && i < (nomi.Length))
    {
        if (note == nomi[i])
            diesis = true;

        i++;
    };

    if (diesis)
    {
        [...] Other code
    }
    else
    {
        url = Application.StartupPath + "\\suoniTastiBianchi\\" + note + ".wav";
        sound = new System.Windows.Media.MediaPlayer();

        sound.Open(new Uri(url));
        sound.Play();

        sounds.Add(sound);
    }
}

private void stopPlay(string note)
{
    for (int i = sounds.Count - 1; i >= 0; i--)
    {
        sounds[i].Stop();
        sounds.RemoveAt(i);
    }
}
私有线程th=null;
private void Form1\u KeyDown(对象发送方,KeyPressEventArgs e)
{
foreach(面板控件中的PictureBox键)
{
字符串名称=key.name;
string[]parts=name.Split(“”);
if(例如KeyChar.ToString()==部分[1])
{
th=新螺纹(按);
开始(新对象[]{key,name});
}
}
}
私有void Form1\u KeyUp(对象发送方,KeyEventArgs e)
{
foreach(面板控件中的PictureBox键)
{
字符串名称=key.name;
string[]parts=name.Split(“”);
if(Convert.ToChar(例如KeyValue.ToString().ToLower()==部分[1])
离开(钥匙、姓名);
}
}
专用void press(对象数据)
{
对象[]数组=(对象[])数据;
PictureBox pressedKey=(PictureBox)数组[0];
字符串名称=(字符串)数组[1];
string[]parts=name.Split(“”);
[…]其他代码
play(parts[1].ToString());
}
私有作废许可(对象发送方,字符串名称)
{
PictureBox pressedKey=发送方为PictureBox;
字符串numero=按按键。名称;
字符串[]部分=数字拆分(“”);
[…]其他代码
stopPlay(部件[1].ToString());
}
列表声音=新列表();
私人虚空演奏(弦乐)
{
int i=0;
字符串url;
布尔-迪西斯=假;
var sound=new System.Windows.Media.MediaPlayer();
而(!直径和长度<(标称长度))
{
如果(注==nomi[i])
死亡=真;
i++;
};
如果(死亡)
{
[…]其他代码
}
其他的
{
url=Application.StartupPath+“\\suoniTastiBianchi\\”+note+“.wav”;
sound=新系统.Windows.Media.MediaPlayer();
打开(新Uri(url));
声音。播放();
声音。添加(声音);
}
}
私人空位暂停播放(弦乐)
{
对于(int i=sounds.Count-1;i>=0;i--)
{
听起来[i].Stop();
声音。RemoveAt(i);
}
}

不要调用press方法或任何需要在单独线程上访问用户控件的方法。您可以在同一线程上调用这些方法。如果不想通过在UI线程上执行所有代码来阻止UI线程,请将代码划分为两个区域:

1) 这需要更新用户控件 2) 这不需要更新用户控件

位于第二个区域的代码可以在单独的线程上执行


你可以通过谷歌搜索“线程关联”来获取更多关于为什么会发生这种情况的信息

@PhilippeParé我看到了那个问题,读了答案,但我不知道如何解决我的问题。这就是我写这个问题的原因,有一个类似的问题,但我的code@Marco,请注意,MediaPlayer是一个。因此,请使用MediaPlayer的调度程序调用其Stop()方法。(关于如何在上面的评论中链接的Q+A中使用DispatcherObject.Dispatcher属性的更多详细信息…@elgonzo对不起,您能为我写一段调用代码吗?因为我不明白如何在我的代码中使用它。从你的问题中不清楚你是在使用Winforms还是WPF。异常消息表明后者;这是WPF中相关例外的措辞。但是您的代码看起来很像Winforms代码。看起来您可能混合了WPF和Winforms对象。在您的情况下,根据Winforms答案,您可能需要
控件.Invoke()
方法,而不是
调度程序.Invoke()
。要使后者在Winforms程序中工作,您会遇到一些问题,因为您的对象通常没有
Dispatcher
属性。不过请注意,
MediaPlayer
对象本身确实有
Dispatcher
属性,因此您可以选择它。它可能在Winforms程序的上下文中仍然有效。请为我写一段代码好吗?请理解如何使用我的代码:)