Please help me to understand what went wrong. I have a progress bar method to start running the progress bar in a task. The Base class is the static class which holds the updated values from another class. Below is my code:
private void startProgressBarBA()
{
int tempBA = 0;
proBing.Maximum = Int32.Parse(cboGeoThreshold.Text);
CancellationTokenSource bingBarToken = new CancellationTokenSource();
Task bingTask = Task.Factory.StartNew(() =>
{
while (!bingBarToken.Token.IsCancellationRequested)
{
if (tempBA != Base.proBaValue)//Reduce the number of same value assigned.
{
try
{
Dispatcher.BeginInvoke(new Action(() =>
{
if (proBing.Value == proBing.Maximum)
{
proBing.Value = 0;
Base.proBaValue = 0;
}
proBing.Value = Base.proBaValue;
tempBA = Base.proBaValue;
baRecord.Content = proBing.Value + "/" + proBing.Maximum;
}
));
}
catch(OutOfMemoryException e)
{
throw e;
}
}
if (Base.checkTaskBA == false)
{
bingBarToken.Cancel();
}
}
},bingBarToken.Token, TaskCreationOptions.LongRunning,TaskScheduler.Default);
}
The exception will occurs after a certain time, and the
Dispatcher.BeginInvoke
has been highlighted. Here is the exception message:
System.OutOfMemoryException was unhandled by user code
HResult=-2147024882
Message=Exception of type 'System.OutOfMemoryException' was thrown.
Source=View
StackTrace:
at View.MainWindow.<>c__DisplayClass21_0.<startProgressBarBA>b__0() in C:\Wade\GeocodingApp\Geocoder_v21_Rev_pcode\View\MainWindow.xaml.cs:line 331
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
InnerException:
How to solve this issue? Is it because the
new Action()
causes the OutOfMemoryException? Thanks for everyone's help.
Just a guess here, but it looks like you have no delay in that "while" loop in your task.
That means you are cycling through that loop very quickly, and are creating a huge number of asynchronous "invoke" messages on the Dispatcher
queue - no doubt this is eating up all the memory....they aren't being processed fast enough so are building up (i.e. must have 100s thousands/maybe millions of "Action" objects created).
Possible solution....put some kind of "wait" in your while loop e.g. a Thread.Sleep(100)
- you don't need to send them out that often to indicate the progress.
private void startProgressBarBA()
{
int tempBA = 0;
proBing.Maximum = Int32.Parse(cboGeoThreshold.Text);
CancellationTokenSource bingBarToken = new CancellationTokenSource();
Task bingTask = Task.Factory.StartNew(() =>
{
while (!bingBarToken.Token.IsCancellationRequested)
{
if (tempBA != Base.proBaValue)//Reduce the number of same value assigned.
{
try
{
Dispatcher.BeginInvoke(new Action(() =>
{
if (proBing.Value == proBing.Maximum)
{
proBing.Value = 0;
Base.proBaValue = 0;
}
proBing.Value = Base.proBaValue;
tempBA = Base.proBaValue;
baRecord.Content = proBing.Value + "/" + proBing.Maximum;
}
));
}
catch(OutOfMemoryException e)
{
throw e;
}
}
if (Base.checkTaskBA == false)
{
bingBarToken.Cancel();
}
Thread.Sleep(100);
}
},bingBarToken.Token, TaskCreationOptions.LongRunning,TaskScheduler.Default);
}