Пустые компоненты в форме при обновлении из потока - PullRequest
0 голосов
/ 08 января 2019

Я создал форму, которая перемещается по экрану влево, но все компоненты формы не заполнены.

Я поместил код для движения в комментарии, и все было хорошо, поэтому проблема в моем коде движения, но я не знаю, в чем проблема.

System.Threading.Thread thread;

private void Form1_Load(object sender, EventArgs e)
{
    thread = new System.Threading.Thread(loop);
    thread.Start();
}

void loop()
{
    this.BeginInvoke((Action)delegate () {
        int x = 0;
        int y = 0;
        int MoveRate = 1;
        Point TopLeft = this.Location;
        Point TopRight = new Point (this.Location.X + this.Width, this.Location.Y);
        while (true)
        {
            x = x + MoveRate;
            this.Location = new Point(x, 150);
            System.Threading.Thread.Sleep(10);
        }
    });     
}

Это должно заставить форму переместиться влево, однако компоненты в Форме пустые.

Ответы [ 2 ]

0 голосов
/ 08 января 2019

Async вариант того же процесса, чтобы проверить что-то другое.
(Основная причина того, что ваш поток не работал должным образом, уже была объяснена. Если вы используете поток и затем вызываете поток пользовательского интерфейса в замкнутом цикле, это более или менее похоже на то, что ваш код не запускается в другом потоке в все: форма не успевает обновить себя или свои элементы управления).

Этот метод добавляет завершение в процедуру прокрутки, когда форма прокручивается за пределами текущих границ экрана. Когда это условие выполнено, цикл while завершается, и задача завершается, перемещая форму в центре экрана.

Задание запускается в событии Shown. Я думаю, что это более уместно, чем событие Load (форма готова для представления здесь).

Обратите внимание, что ни эта Задача, ни Поток не добавляют никакой проверки на событие Form.FormClosing, чтобы отменить асинхронный процесс. Если форма будет закрыта во время прокрутки, у вас, скорее всего, будет исключение (форма была удалена, поэтому больше не обрабатывать).

private async Task Scroller(int ScreenWidth)
{
    int x = 0;
    int MoveRate = 2;

    while (true)
    {
        x += MoveRate;
        this.BeginInvoke(new MethodInvoker(() => { this.Location = new Point(x, 150);}));
        await Task.Delay(10);
        if (x > ScreenWidth) break;
        }
    };
}

private async void MyAppMainForm_Shown(object sender, EventArgs e)
{
    int ScreenWidth = Screen.FromHandle(this.Handle).Bounds.Width;
    await this.Scroller(ScreenWidth);
    this.Location = new Point((ScreenWidth - this.Width) / 2 , 150);
}
0 голосов
/ 08 января 2019

Давайте посмотрим на метод loop():

void loop()
{
    this.BeginInvoke((Action)delegate () {
        int x = 0;
        int y = 0;
        int MoveRate = 1;
        Point TopLeft = this.Location;
        Point TopRight = new Point (this.Location.X + this.Width, this.Location.Y);
        while (true)
        {
            x = x + MoveRate;
            this.Location = new Point(x, 150);
            System.Threading.Thread.Sleep(10);
        }
    });     
}

Этот код немедленно вызывает делегата обратно в основной поток пользовательского интерфейса. Делегат запускает цикл while(true), который никогда не завершается. Как только цикл начинает выполняться, поток пользовательского интерфейса полностью закрывается без надежды когда-либо ответить на другие сообщения о событиях, включая события рисования.

Попробуйте вместо этого:

void loop()
{
    int x = 0;
    int MoveRate = 1;

    while(true)
    {
        x += MoveRate;
        this.BeginInvoke((Action)delegate () { this.Location = new Point(x, 150); });
        System.Threading.Thread.Sleep(16);
    } 
}

Это все тот же код (за исключением вещей, которые ничего не делали), но теперь расположены так, что делегат вызывается внутри цикла. Поток пользовательского интерфейса блокируется только на короткое время, и затем управление возвращается обратно в поток цикла, который некоторое время будет находиться в спящем режиме, прежде чем снова беспокоить пользовательский интерфейс. Вызов даже достаточно прост, я смог переписать его в одну строку.

Обратите внимание, что я также увеличил время ожидания, потому что это все равно дает вам 60 кадров в секунду.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...