Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# BeginInvoke方法何时运行?_C#_Multithreading_Winforms - Fatal编程技术网

C# BeginInvoke方法何时运行?

C# BeginInvoke方法何时运行?,c#,multithreading,winforms,C#,Multithreading,Winforms,我有两个线程使用BeginInvoke方法将某些Windows窗体对象(面板和标签)的可见性属性更改为false。问题是我不确定更改何时发生。我可以看到面板不在那里(因此BeginInvoke方法起作用),但是我检查可见性状态的if条件在第一次激活表单时总是返回true bool notVisible = false; private void LunchMainScreen_Activated(object sender, EventArgs e) { String CurrentS

我有两个线程使用BeginInvoke方法将某些Windows窗体对象(面板和标签)的可见性属性更改为false。问题是我不确定更改何时发生。我可以看到面板不在那里(因此BeginInvoke方法起作用),但是我检查可见性状态的if条件在第一次激活表单时总是返回true

bool notVisible = false;

private void LunchMainScreen_Activated(object sender, EventArgs e) {
    String CurrentSite = "";
    List<DateTime> availableDates = new List<DateTime>();

    // Get available dates
    Thread availableDatesThread = new Thread(delegate() {
        availableDates = LunchUserPreferences.GetUserAvailableDates();
            changeObjVisible(notVisible, selectAvailabilityPanel);
            changeObjVisible(notVisible, whenLbl);
        }
    });
    availableDatesThread.Start();

    // Get user current site
    Thread checkSiteThread = new Thread(delegate() {
        CurrentSite = LunchUserPreferences.GetUserSite();
            changeObjVisible(notVisible, selectSitePanel);
            changeObjVisible(notVisible, whereLbl);
        }
        updateText(CurrentSite, CurrentSiteSetLbl);
    });
    checkSiteThread.Start();

    while (selectSitePanel.Visible == false && selectAvailabilityPanel.Visible == false) {
         // it NEVER gets here, even though the panels are NOT visible when the program loads
         WhoLunchTable.Visible = false;
         WhoLunchTable.SuspendLayout();

         listOfAvailableGroups.Clear();
         WhoLunchTable.Controls.Clear();
         WhoLunchTable.RowStyles.Clear();

         PopulateTable();

         WhoLunchTable.Visible = true;
         WhoLunchTable.ResumeLayout();
         break;
    }
}

private delegate void changeObjVisibleDelegate(bool visibility, object obj);

private void changeObjVisible(bool visibility, object obj) {
    if (this.InvokeRequired) {
        this.BeginInvoke(new changeObjVisibleDelegate(changeObjVisible), new object[] { visibility, obj });
        return;
    }

    // downcast to the correct obj 
    if (obj is Panel) {
        Panel panel = (Panel)obj;
        panel.Visible = visibility;
    }

    if (obj is Label) {
        Label lbl = (Label)obj;
        lbl.Visible = visibility;
    }
}

private delegate void updateTextDelegate(string text, Label lbl);
private void updateText(string text, Label lbl) {
    if (this.InvokeRequired) {
        this.BeginInvoke(new updateTextDelegate(updateText), new object[] { text, lbl });
        return;
    }

    lbl.Text = text;
}

当代码第一次没有进入while循环时读取代码,因为selectSitePanel.Visible和selectAvailabilityPanel.Visible为true:这是因为AvailabledTestThread.Start()为true;和checkSiteThread.Start();已开始但尚未完成;这两个调用没有阻塞,因此代码继续并跳过。 同时,两个backgrund线程完成,因此第二次引发“Activated”事件时,变量值是“correct”(至少在上一个周期中是正确的)

不必等待线程完成,您就可以在获得所需值的结果之前快速浏览代码

换句话说,最好不要使用后台线程来更新您需要的接口


如果需要,您可以继续使用代码,但在两个单独的函数中移动“while”部分:当线程完成其工作并在此时刷新窗口时,可以调用它们,而不是在“activate”中事件。

据我所知,您正在使用后台线程设置WinForms控件的属性。WinForms文档声明,您只能在创建WinForms控件的同一线程上与它们交互。为什么你需要使用一个后台线程呢?或者它们是在不同的线程上创建的,而不是调用
午餐主屏幕激活()。我选择使用线程与WinForms控件交互,这样它们可以同时运行(考虑到一个与另一个无关),从而减少表单完成加载所需的时间。任何关于如何通过不同流程实现相同目标的建议都是非常受欢迎的:)您确定存在性能问题吗?如果窗体即使在主线程上设置可见性时也可以正常加载,那么就没有理由使用线程。此外,我读到的所有内容都表明,对WinForms控件的所有访问必须位于创建它们的同一线程上。这次你也许可以侥幸逃脱,但我也可以看到这一点随机失败。你的回答没有解决问题,但给了我解决问题的思路。这看起来不是最好的解决方案,所以我将用新代码更新我的问题,看看是否还有进一步的改进需要做。谢谢
while (availableDatesThread.IsAlive || checkSiteThread.IsAlive) {
    // At least one thread is still alive, keeps checking it...

    if (!availableDatesThread.IsAlive && !checkSiteThread.IsAlive) {
        // Both threads should be dead now and the panels not visible

         WhoLunchTable.Visible = false;
         WhoLunchTable.SuspendLayout();

         listOfAvailableGroups.Clear();
         WhoLunchTable.Controls.Clear();
         WhoLunchTable.RowStyles.Clear();

         PopulateTable();

         WhoLunchTable.Visible = true;
         WhoLunchTable.ResumeLayout();
         break;
    }
}