Heather Czerniak Ответов: 1

C# как мне получить форму от backgroundworker, чтобы показать ее полностью?


I'm writing a C# WinForms app in VS 2017Professional and I'm having trouble getting a "progress form" to show up on the screen completely. It has a label and a picturebox playing an animated GIF. This form is run from a backgroundworker.

For the most part, it's working fine, except that the progress form that shows while a file is being opened on the main form looks like a light gray rectangle. Inside of it there is a small rectangle at the top outlining where a label is supposed to show and a larger rectangle below it where the picturebox is supposed to show. I'd upload an image of it if I could. How do I get the whole progress form and its controls to show up completely?


Update: I started this project in VS 2013 Ultimate and now I'm working on it in VS 2017 Pro. I simply started working on it in VS 2017. No sign of trouble in the process, though.


Что я уже пробовал:

Here's the code I'm working with. It's from the main form running on the UI thread: 

private void OpenGame(string filepath)
{
    try
    {
        BackgroundWorker BgwSP = new BackgroundWorker();
        BgwSP.WorkerReportsProgress = BgwSP.WorkerSupportsCancellation = true;
        BgwSP.DoWork += BgwSP_DoWork;
        BgwSP.RunWorkerCompleted += BgwSP_RunWorkerCompleted;
        BgwSP.RunWorkerAsync(filepath);

        // Now set up the filestream andn binaryreader to read the contents of the file.
        FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read);
        BinaryReader br = new BinaryReader(fs);

        // Next we get the Game Info and load it all into the GameInfo class.
        GameInfo.strGameVersion = br.ReadString();
        if (GameInfo.strGameVersion == "1.0" || (GameInfo.strGameVersion == "2.0" && GameInfo.strGameVersion == "Standard Game Project"))
        {
            this.BackColor = SystemColors.AppWorkspace;
            clsOpenStandardGame OpenStandardGame = new clsOpenStandardGame();
            OpenStandardGame.OpenStdGame(filepath);
            this.GameInfo = OpenStandardGame.ReturnGameInfo();
            this.lstQuestions = OpenStandardGame.ReturnlstStdQuestions();
            this.Tiebreaker = OpenStandardGame.ReturnTiebreaker();
        }
        else if (GameInfo.strGameVersion == "2.0" && GameInfo.strGameType == "Multi-Category Game Project")
        {
            this.BackColor = SystemColors.AppWorkspace;
            clsOpenMultiCategoryGame OpenMultiCatGame = new clsOpenMultiCategoryGame();
            OpenMultiCatGame.OpenMultiCatGame(filepath);
            this.GameInfo = OpenMultiCatGame.ReturnGameInfo();
            this.lstCategories = OpenMultiCatGame.ReturnlstCategories();
            this.Tiebreaker = OpenMultiCatGame.ReturnMultiCatTiebreaker();
        }

        // Set up the Intro Screen's mode to Full Screen or Normal Screen.
        if (Properties.Settings.Default.blFullScreenOnGameOpened == true)
            tsbtnFullScreen.PerformClick();

        // Now we set up the title at the top of the main form.
        this.Text = Path.GetFileNameWithoutExtension(filepath).ToString() + " - Trivia Player v2.0";

        // Fix the status strip.
        tslblStatus.Text = "Ready";
        ssStatusStrip.Refresh();

        // And finally, set up the game and prepare to play it.
        SetUpTheGame();
    }
    catch (Exception ex)
    {
        // Suddenly, something went terribly wrong!
        MessageBox.Show(ex.ToString(), "oops.", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

private void BgwSP_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // OK, the game is done opening, now kill the progress form.
    foreach (frmShowProgress frm in this.OwnedForms)
    {
        if (frm is frmShowProgress)
            frm.Dispose();
    }
}

private void BgwSP_DoWork(object sender, DoWorkEventArgs e)
{
    // Get the filename.
    string strFilepath = Path.GetFileNameWithoutExtension((string)e.Argument);

    // Now show the progress form.
    frmShowProgress frmSP = new frmShowProgress(strFilepath);
    frmSP.BringToFront();
    frmSP.Show();

    // Now let's goof off until we have to close the progress form.
    BackgroundWorker worker = sender as BackgroundWorker;

    for (int i = 0; i <= 100; i++)
    {
        worker.ReportProgress(i);
        Thread.Sleep(100);

        if (worker.CancellationPending && worker.IsBusy)
        {
            frmSP.Dispose();
            e.Cancel = true;
            return;
        }
    }
}

1 Ответов

Рейтинг:
2

Dave Kreskowiak

Просто, ты не знаешь.

Любой элемент пользовательского интерфейса, формы, элементы управления и настройка / получение их свойств всегда должны быть созданы и доступны в потоке пользовательского интерфейса (startup thread). Вы не можете сделать это из любого другого потока, в том числе и внутри BackGroundWorker.

Вы можете отправлять обновления прогресса через событие ProgressChanged BackgroundWorker.


Heather Czerniak

Спасибо за ответ, Дейв. Другими словами, я могу просто создать экземпляр frmSP в потоке пользовательского интерфейса и закрыть его, не так ли? Я поместил его в backgroundworker, потому что думал, что распределение задач по двум потокам 1) ускорит выполнение кода и 2) снимет нагрузку с потока пользовательского интерфейса.

Dave Kreskowiak

Да