Question

i am trying to display a usercontrol to my form. the usercontrol is a picturebox with a gif-image from a bird.

i am trying to do this:

//main form
class Form1
{
    //play button
    private void gameButton1_Click(object sender, EventArgs e)
    {
        startPanel.Visible = false;
        Game g = new Game(this.gamePanel1);
        g.Start();
    }
}

class Game
{
    //is set to true after starting game

    public Game(gamePanel Display)
    {
        this.Display = Display;
    }

    bool Running = false;

    public gamePanel Display;

    public void Start()
    {

        Thread create_BirdsThread = new Thread(new ThreadStart(create_Birds));
        create_BirdsThread.Start();
        Running = true;

    }

    private void create_Birds()
    {
        while (Running)
        {

            //Display is a variable from class 'GamePanel'
            Display.CreateBirds();
            Display.Refresh();

            //this is just to test that one bird works
            Running = false;
        }
    }
}


class gamePanel : UserControl
{
    public void CreateBirds()
    {
        yBird y = new yBird();
            y.BackColor = System.Drawing.Color.Transparent;
            y.Location = new System.Drawing.Point(32, 56);
            y.Size = new System.Drawing.Size(96, 65);
            y.TabIndex = 1;

            if (this.InvokeRequired)
            {
                this.BeginInvoke((MethodInvoker)delegate()
                {
                    this.Controls.Add(y);
                });
            }
            else
            {
                this.Controls.Add(y);
            }
            y.Visible = true;
            y.BringToFront();
    }
}

but it doesn't display a bird on my screen. how to fix this?

thanks!

*Edit :

i added the code from my main form and the Game.Start() method

Was it helpful?

Solution 2

i have already fixed it.

i just changed this

if (this.InvokeRequired)
            {
                this.BeginInvoke((MethodInvoker)delegate()
                {
                    this.Controls.Add(y);
                });
            }

to this

if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(this.yellow));

            }

OTHER TIPS

Sure, this code cannot work. In order for Control.Begin/Invoke() to work, .NET first needs to know what specific thread your code needs to run on. Which it figures out from the Handle property. Which tells it which specific thread owns the window, the underlying winapi call is GetWindowThreadProcessId().

But that's a chicken-and-egg problem in your code. The native window doesn't get created until your code calls the Controls.Add() method. Which must run on the UI thread of your program, the thread that owns the Form object. Windows does not permit a child window to be owned by a different thread.

So it just doesn't know what thread to invoke to. If you force the handle to be created then your program just dies a different way because of the ownership rule.

Keep your eye on the bigger problem: you are creating a thread to run code that takes a handful of nanoseconds. These property assignments are very cheap. The real work is creating the window, that takes many microseconds. Which you want (and need) to run on the UI thread. So there's just no benefit to using a thread at all, the UI thread won't sweat spending a few nanoseconds on setting the properties as well.

So remove the thread completely to get ahead. If you are doing something else that's slow, like loading the image, then that can easily be done on a worker thread.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top