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}%";
}
我在 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}%";
}