C# WinForm:当从 BackgroundWorker_ProgressChanged 事件调用时,contextMenuStrip 在 .Show() 方法之后抛出 InvalidOperationException

C# WinForm: contextMenuStrip throws InvalidOperationException after .Show() method when called from BackgroundWorker_ProgressChanged event

我在 C# 中有一个带有 TrayIcon 的 WindowsForm,包括一个带有 ToolStripTextBox 的 contextMenuStrip、一个 FileSystemWatcher 和一个 BackgroundWorker。

FileSystemWatcher 在创建新文件时引发事件,然后启动 BackgroundWorker。 BackgroundWorker 报告更新 ProgressChanged 事件处理程序中 TrayIcon 上的 ToolStripTextBox 的进度。

奇怪的是,只要 ToolStripMenu 自程序启动以来一直不可见,这就可以正常工作。一旦我右键单击 TrayIcon 以显示 ToolStripMenu(无论 BackgroundWorker 是否处于空闲状态),每次我尝试更新其 .Text 属性。

当我从按钮单击事件启动 BackgroundWorker 时,它也一切正常。我可以看到 ToolStripTextBox 正在更新。

从 FileSystemWatcher 事件启动 BackgroundWorker 有何不同?或者更确切地说,显示 contextMenuStrip 后有什么不同? contextMenuStrip显示后是否属于另一个线程?

我可能会找到另一种方式来显示进度而不是 ToolStripTextBox,但我很想知道是什么原因造成的。如果您能提供帮助,我将非常高兴。

下面是最简单的代码示例。


public partial class Form1 : Form
{
    FileSystemWatcher watcher = new FileSystemWatcher();
    string watcherpath = @"C:\Temp\files";
    BackgroundWorker bgw = new BackgroundWorker();
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        watcher.Path = watcherpath;
        watcher.Created += Watcher_Created;
        watcher.EnableRaisingEvents = true;
        bgw = new BackgroundWorker();
        bgw.DoWork += Bgw_DoWork;
        bgw.RunWorkerCompleted += Bgw_RunWorkerCompleted;
        bgw.WorkerSupportsCancellation = true;
        bgw.WorkerReportsProgress = true;
        bgw.ProgressChanged += Bgw_ProgressChanged;
    }

    private void Bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        toolStripTextBox1.Text = $"Progress: {e.ProgressPercentage}%";
    }

    private void Bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        MessageBox.Show("Done!");
    }

    private void Bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 1; i <= 10; i++)
        {
            Thread.Sleep(1000);
            (sender as BackgroundWorker).ReportProgress(i * 10);
        }
    }

    private void Watcher_Created(object sender, FileSystemEventArgs e)
    {
        File.Delete(e.FullPath);
        bgw.RunWorkerAsync();
    }

    private void toolStripMenuItem1_Click(object sender, EventArgs e)
    {
        this.Close();
    }

    private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Right)
            contextMenuStrip1.Show(Cursor.Position);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        bgw.RunWorkerAsync();
    }
}***

请尝试以下代码

    private void Bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
         SetToolStripText(e.ProgressPercentage)
    }

    private void SetToolStripText(object ProgressPercentage)
    {
            this.BeginInvoke((MethodInvoker)delegate { this.toolStripTextBox1.Text = $"Progress: {e.ProgressPercentage}%";
    }