简体   繁体   中英

Why am I getting this InvalidOperationException in this C# wpf application?

I have a C# (WPF) program that searches through files in a directory, and I wanted a progress bar to show my progress searching through the files in the directory (since there could be thousands of files in a directory).

I decided to use background workers so that the progress bar updates correctly (which isn't happening, but that's not my biggest problem).

Currently what happens is it SOMETIMES works which is super weird, but most times I get this error. The only time I don't get this error is if I add a MessageBox.Show(); in the foreach(document in myDirectory) loop to slow it down and view what number file it's on. Then it only errors out every so often.

Can anyone explain to me why I'm getting this error, and how to fix it? Also, if you think there's a better method to show the progress bar, please don't hesitate to correct what I'm doing.

My error

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

Stack Trace

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

The code you posted can't even compile. It's not syntactically correct. Without a good, minimal , complete code example that reliably reproduces the problem, it's impossible to know for sure what the problem is, never mind what the best solution is. But there are some clues in your post:

  • The exception is clearly stating that your code is attempting to call the ReportProgress() method on a BackgroundWorker object that represents an operation that has already been completed.
  • The code that starts the BackgroundWorker creates a new instance for each document in your myDirectory collection, and assigns the reference of this new instance to a single variable, backgroundWorker1 .

Since you have multiple instances of BackgroundWorker running concurrently, but can only keep track of a single instance at a time, it is most likely that an instance started later is completing first, and an instance started earlier is trying to report progress, but can only use the reference of the instance that started later to do so. Since that later-started instance has already completed, the exception is thrown.

One fix would be to simply have the CalculateProgress() method take as a parameter the BackgroundWorker reference that is sent to the DoWork event handler. That way, each instance of the BackgroundWorker would use itself to report progress instead of trying to use the most-recently-started one.

But it seems unlikely that it's actually a good idea for you to use more than one BackgroundWorker instance in the first place. A better implementation is a single instance of BackgroundWorker , where the loop that enumerates the documents is in that worker's DoWork event handler.

It's my hope that the above is enough information for you to recognize the error in your code and fix it. If not, please provide a good code example, so that it can be modified so as to illustrate what I mean above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM