The problem is that your
DataImporter
class is firing its
ProgressChanged
event from a background thread. As a result, the code in the
bgw_ProgressChanged
handler cannot access or modify the UI.
You could change the handler to invoke the code on the UI thread:
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (InvokeRequired)
{
Invoke((ProgressChangedEventHandler)bgw_ProgressChanged, sender, e);
return;
}
...
}
Or you could add an extra layer of indirection:
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
ImportData dataImporter = new ImportData();
dataImporter.ProgChanged += imp_ProgressChanged;
dataImporter.Import();
}
private void imp_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
bgw.ReportProgress(e.ProgressPercentage, e.UserState);
}
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
...
}
Or, you could modify your
ImportData
class to raise the event on the UI thread:
public class ImportData
{
private readonly SendOrPostCallback _progressReporter;
private AsyncOperation _asyncOperation;
public ImportData()
{
_progressReporter = arg => OnProgChanged((ProgressChangedEventArgs)arg);
}
public ProgressChangedEventHandler ProgChanged;
protected virtual void OnProgChanged(ProgressChangedEventArgs e)
{
ProgressChangedEventHandler handler = ProgChanged;
if (handler != null) handler(this, e);
}
private void UpdateProgress(int percent, string state)
{
ProgressChangedEventArgs arg = new ProgressChangedEventArgs(percent, state);
if (_asyncOperation != null)
{
_asyncOperation.Post(_progressReporter, arg);
}
else
{
OnProgChanged(arg);
}
}
public void Import()
{
_asyncOperation = AsyncOperationManager.CreateOperation(null);
UpdateProgress(100, "Work Completed");
}
}