为什么我会在此 C# wpf 应用程序中收到此 InvalidOperationException?
Why am I getting this InvalidOperationException in this C# wpf application?
我有一个搜索目录中文件的 C# (WPF) 程序,我想要一个进度条来显示搜索目录中文件的进度(因为目录中可能有数千个文件) .
我决定使用后台工作者,以便进度条正确更新(这并没有发生,但这不是我最大的问题)。
目前发生的情况是它有时会工作,这非常奇怪,但大多数时候我都会收到此错误。我唯一没有收到此错误的情况是,如果我在 foreach(document in myDirectory)
循环中添加一个 MessageBox.Show();
以减慢它的速度并查看它所在的数字文件。然后它只会偶尔出错。
谁能向我解释为什么会出现此错误,以及如何解决?另外,如果您认为有更好的方法来显示进度条,请随时纠正我的做法。
我的错误
An exception of type 'System.InvalidOperationException' occurred in System.dll but was not handled in user code
Additional information: This operation has already had OperationCompleted called on it and further calls are illegal.
myApp.xaml.cs
BackgroundWorker backgroundWorker1;
public void searchFiles()
{
//50 files in the directory
int fileCount = 50;
int documentCounter = 0;
//For every file in the directory
foreach(document in myDirectory)
{
//increment the file count
documentCounter++;
FileSearchProgressBar(documentCounter, fileCount);
}
}
private void FileSearchProgressBar(int currentDocNumber, int count)
{
backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += (obj, ea) => CalculateProgress(currentDocNumber, count);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(progressReport);
backgroundWorker1.RunWorkerAsync();
}
void progressReport(object sender, ProgressChangedEventArgs e)
{
progBar.Value = e.ProgressPercentage;
}
private void CalculateProgress(int currentDocNumber, int count)
{
//This is where the error is reporting
backgroundWorker1.ReportProgress(currentDocNumber * (100 / count));
}
EDIT1
堆栈跟踪
System.InvalidOperationException: This operation has already had OperationCompleted called on it and further calls are illegal.
at System.ComponentModel.AsyncOperation.VerifyNotCompleted()
at System.ComponentModel.AsyncOperation.Post(SendOrPostCallback d, Object arg)
at System.ComponentModel.BackgroundWorker.ReportProgress(Int32 percentProgress, Object userState)
at System.ComponentModel.BackgroundWorker.ReportProgress(Int32 percentProgress)
at HR_Search_Program.MainWindow.CalculateProgress(Int32 currentDocNumber, Int32 count) in c:\Users\myname\Documents\Visual Studio 2013\Projects\myproject\myproject\MainWindow.xaml.cs:line 589
您 post 编写的代码甚至无法编译。它在语法上不正确。如果没有 a good, minimal, complete code example 可靠地重现问题,就不可能确定问题是什么,更不用说最佳解决方案是什么了。但是你的 post:
中有一些线索
- 异常清楚地表明您的代码正试图在表示已完成的操作的
BackgroundWorker
对象上调用 ReportProgress()
方法。
- 启动
BackgroundWorker
的代码为您的 myDirectory
集合中的每个文档创建一个新实例,并将该新实例的引用分配给单个变量 backgroundWorker1
。
由于您同时有多个 BackgroundWorker
运行 实例,但一次只能跟踪一个实例,很可能是后启动的实例先完成,并且较早启动的实例正在尝试报告进度,但只能使用较晚启动的实例的引用来这样做。由于后来启动的实例已经完成,因此抛出异常。
一个解决方法是让 CalculateProgress()
方法将发送到 DoWork
事件处理程序的 BackgroundWorker
引用作为参数。这样,BackgroundWorker
的每个实例都会使用 自身 来报告进度,而不是尝试使用最近启动的实例。
但是一开始就使用多个 BackgroundWorker
实例似乎不太可能是个好主意。更好的实现是 BackgroundWorker
的单个实例,其中枚举文档的循环位于该工作人员的 DoWork
事件处理程序中。
我希望以上信息足以让您识别代码中的错误并修复它。如果没有,请提供一个好的代码示例,以便可以修改它以说明我上面的意思。
我有一个搜索目录中文件的 C# (WPF) 程序,我想要一个进度条来显示搜索目录中文件的进度(因为目录中可能有数千个文件) .
我决定使用后台工作者,以便进度条正确更新(这并没有发生,但这不是我最大的问题)。
目前发生的情况是它有时会工作,这非常奇怪,但大多数时候我都会收到此错误。我唯一没有收到此错误的情况是,如果我在 foreach(document in myDirectory)
循环中添加一个 MessageBox.Show();
以减慢它的速度并查看它所在的数字文件。然后它只会偶尔出错。
谁能向我解释为什么会出现此错误,以及如何解决?另外,如果您认为有更好的方法来显示进度条,请随时纠正我的做法。
我的错误
An exception of type 'System.InvalidOperationException' occurred in System.dll but was not handled in user code
Additional information: This operation has already had OperationCompleted called on it and further calls are illegal.
myApp.xaml.cs
BackgroundWorker backgroundWorker1;
public void searchFiles()
{
//50 files in the directory
int fileCount = 50;
int documentCounter = 0;
//For every file in the directory
foreach(document in myDirectory)
{
//increment the file count
documentCounter++;
FileSearchProgressBar(documentCounter, fileCount);
}
}
private void FileSearchProgressBar(int currentDocNumber, int count)
{
backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += (obj, ea) => CalculateProgress(currentDocNumber, count);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(progressReport);
backgroundWorker1.RunWorkerAsync();
}
void progressReport(object sender, ProgressChangedEventArgs e)
{
progBar.Value = e.ProgressPercentage;
}
private void CalculateProgress(int currentDocNumber, int count)
{
//This is where the error is reporting
backgroundWorker1.ReportProgress(currentDocNumber * (100 / count));
}
EDIT1
堆栈跟踪
System.InvalidOperationException: This operation has already had OperationCompleted called on it and further calls are illegal.
at System.ComponentModel.AsyncOperation.VerifyNotCompleted()
at System.ComponentModel.AsyncOperation.Post(SendOrPostCallback d, Object arg)
at System.ComponentModel.BackgroundWorker.ReportProgress(Int32 percentProgress, Object userState)
at System.ComponentModel.BackgroundWorker.ReportProgress(Int32 percentProgress)
at HR_Search_Program.MainWindow.CalculateProgress(Int32 currentDocNumber, Int32 count) in c:\Users\myname\Documents\Visual Studio 2013\Projects\myproject\myproject\MainWindow.xaml.cs:line 589
您 post 编写的代码甚至无法编译。它在语法上不正确。如果没有 a good, minimal, complete code example 可靠地重现问题,就不可能确定问题是什么,更不用说最佳解决方案是什么了。但是你的 post:
中有一些线索- 异常清楚地表明您的代码正试图在表示已完成的操作的
BackgroundWorker
对象上调用ReportProgress()
方法。 - 启动
BackgroundWorker
的代码为您的myDirectory
集合中的每个文档创建一个新实例,并将该新实例的引用分配给单个变量backgroundWorker1
。
由于您同时有多个 BackgroundWorker
运行 实例,但一次只能跟踪一个实例,很可能是后启动的实例先完成,并且较早启动的实例正在尝试报告进度,但只能使用较晚启动的实例的引用来这样做。由于后来启动的实例已经完成,因此抛出异常。
一个解决方法是让 CalculateProgress()
方法将发送到 DoWork
事件处理程序的 BackgroundWorker
引用作为参数。这样,BackgroundWorker
的每个实例都会使用 自身 来报告进度,而不是尝试使用最近启动的实例。
但是一开始就使用多个 BackgroundWorker
实例似乎不太可能是个好主意。更好的实现是 BackgroundWorker
的单个实例,其中枚举文档的循环位于该工作人员的 DoWork
事件处理程序中。
我希望以上信息足以让您识别代码中的错误并修复它。如果没有,请提供一个好的代码示例,以便可以修改它以说明我上面的意思。