-1

I know other users asked this question but I don't know how to solve my problem. Below there's my code (sorry, maybe it's too long). Visual Studio says "The calling thread cannot access this object because a different thread owns it" on the line sounds[i].Stop();. Why? And How to solve this problem?
Thank'you so much!

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);
    }
}
Marco
  • 1
  • @PhilippeParé I saw that question, read the answers but I don't know how to solve my problem. This is why I wrote this question, with a similar problem but with my code – Marco Jun 02 '17 at 20:53
  • @Marco, note that MediaPlayer is a [DispatcherObject](https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcherobject(v=vs.110).aspx). Hence use the MediaPlayer's dispatcher to invoke its Stop() method. (Further details how to use the DispatcherObject.Dispatcher property in the Q+A linked in the comment above...) –  Jun 02 '17 at 20:57
  • @elgonzo sorry can you please write the piece of code for me with the invoke? because I didn't understand how to use it in my code. – Marco Jun 02 '17 at 21:11
  • It is not clear from your question whether you are using Winforms or WPF. The exception message suggests the latter; that's the wording of the relevant exception in WPF. But your code looks a lot like Winforms code. It seems you may be mixing WPF and Winforms objects. In your case, you may require the `Control.Invoke()` method, per the Winforms answer, rather than `Dispatcher.Invoke()`. You'll have some trouble getting the latter to work inside a Winforms program, because your objects mostly won't have a `Dispatcher` property. – Peter Duniho Jun 02 '17 at 21:46
  • Note though, that the `MediaPlayer` object itself does have a `Dispatcher` property, so you may have that as an option. It may still work in the context of a Winforms program. – Peter Duniho Jun 02 '17 at 21:48

1 Answers1

0

Do not call press method or any method that needs to access user controls on a separate thread. you can call those methods on the same thread. If you do not want to block the UI thread by executing all of your code on the UI thread then partition your code into 2 areas:

1) that needs to update User controls 2) that does not need to update User controls

the code that lies in second area can be executed on separate threads.

You can google 'Thread Affinity' for more information about why this is happening.

Farooq Hanif
  • 1,779
  • 1
  • 15
  • 22
  • con you please write the piece of code for me? Just per understand how to do that with my code :) – Marco Jun 02 '17 at 21:30