“在标签上”之前,无法在控件上调用“调用”或“BeginInvoke”

时间:2018-04-02 07:17:01

标签: c# multithreading winforms invoke

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

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

Screenshot from the app

只要上传完成一次就行了,我的意思是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

1 个答案:

答案 0 :(得分:3)

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

正如in the comments正确指出Evk一样,timercount是非静态的,因此它们专用于表单的每个实例。