【问题标题】:"Invoke or BeginInvoke cannot be called on a control until" on a Label“Invoke 或 BeginInvoke 不能在控件上调用,直到”在标签上
【发布时间】:2018-09-11 09:55:41
【问题描述】:

我已阅读与此问题相关的几个问题/答案,但找不到适用于问题的解决方案。

我有一个表单 (MainForm) 和一个按钮 (Upload)。当我单击按钮时(从组合框中选择要上传到服务器的文件后),它会打开另一个表单(UploadBackupForm)并将文件上传到服务器。上传过程控制在UploadBackupForm,表单如下:

只要上传一次就有效,我的意思是,UploadBackupForm 被调用一次。我第二次点击上传按钮时,UploadBackupForm 打开并且(上传一些数据后)它抛出一个错误说:

System.InvalidOperationException: '在创建窗口句柄之前,不能对控件调用 Invoke 或 BeginInvoke。'

在此特定行:

DurationLabel.Invoke((MethodInvoker)delegate
{
    DurationLabel.Text = Count2Duration(count);
});

这让我感到困惑,因为它在完成一次时有效,第二次无效。我有 C# 的基础知识,所以我不知道是什么原因造成的以及如何解决它。

MainForm:

private void Upload2ServerButton_OnClick(object sender, EventArgs e)
{
    Form UBF = new UploadBackupForm();
    UBF.ShowDialog();
}

UploadBackupForm:

public partial class UploadBackupForm : Form
{
    public UploadBackupForm()
    {
        InitializeComponent();
    }

    public static System.Timers.Timer timer = new System.Timers.Timer();
    public static int count = 0;

    private void UploadBackup_Load(object sender, EventArgs e)
    {
        timer.Interval = 1000;

        timer.Elapsed += new ElapsedEventHandler(delegate {
            count++;
            // didn't do any good (this.IsHandleCreated or DurationLabel.IsHandleCreated)
            // if (!this.IsHandleCreated)
            // {
                // this.CreateControl();
            // }
            DurationLabel.Invoke((MethodInvoker)delegate
            {
                DurationLabel.Text = Count2Duration(count);
            });
        });

        // upload the archive to the server
        new Thread((ThreadStart)delegate
        {
            FTP.Item[] items = FTP.ListDirectoryDetails(DataIO.FTP.Server, DataIO.FTP.Username, DataIO.FTP.Password, DataIO.FTP.UploadDir);

            // here, I upload the file to the server and update the progress bar and the uploaded / total labels

【问题讨论】:

  • timercount 设为非静态(删除static 关键字)。关闭表单时也停止该计时器。
  • @Evk 删除 static 有效。谢谢你。上传完成后(在表单关闭之前)计时器停止。我真的应该阅读更多关于 C# 的内容:) 这也是一个简单的错误(因为它看起来像一个)还是还有更多?如果有,您可以发布答案,我会接受。
  • 我认为这很简单,其他人可能不会,这是主观的:)
  • 哈哈,没错。无论如何,BartoszKP 详细阐述了这个问题。会的:)

标签: c# multithreading winforms invoke


【解决方案1】:

因为timer 变量是静态的,所以即使在表单关闭后它仍然存在。它包含对代表的引用,该代表持有对表单的引用,因此以前的实例在应用程序的整个生命周期中都保持活动状态。此外,单个 timer 将回调与当前实例一起发布到所有先前实例。

正如Evk 正确指出的in the comments,将timercount 设为非静态,以便它们专用于表单的每个实例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-18
    • 2021-05-14
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多