I have the following code from 'Samples for Parallel Programming with the .NET Framework' MSDN when I was trying to cancel the Genetic generations of monkeys in debugging mode I am getting 'OperationCanceledException was unhandled by user code' on line token.ThrowIfCancellationRequested();. I have added last resort of exception handling 'UnobservedTaskException' but the code is never reaching there. Please help me in finding the problem here:
public MainForm()
{
InitializeComponent();
txtTarget.Text = _targetText;
_uiTasks = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
}
void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
e.SetObserved();
}
private int _currentIteration;
private CancellationTokenSource _cancellation;
private void btnRun_Click(object sender, EventArgs e)
{
if (_cancellation == null)
{
_cancellation = new CancellationTokenSource();
GeneticAlgorithmSettings settings = new GeneticAlgorithmSettings { PopulationSize = Int32.Parse(txtMonkeysPerGeneration.Text) };
txtBestMatch.BackColor = SystemColors.Window;
lblGenerations.BackColor = SystemColors.Control;
lblGenPerSec.Text = lblGenerations.Text = "-";
lblElapsedTime.Text = "0";
btnRun.Text = "Cancel";
chkParallel.Visible = false;
_startTime = _lastTime = DateTimeOffset.Now;
timerElapsedTime.Start();
// Run the work in the background
_cancellation = new CancellationTokenSource();
var token = _cancellation.Token;
bool runParallel = chkParallel.Checked;
Task.Factory.StartNew(() =>
{
// Create the new genetic algorithm
var ga = new TextMatchGeneticAlgorithm(runParallel, _targetText, settings);
TextMatchGenome? bestGenome = null;
// Iterate until a solution is found or until cancellation is requested
for (_currentIteration = 1; ; _currentIteration++)
{
token.ThrowIfCancellationRequested();
// Move to the next generation
ga.MoveNext();
// If we've found the best solution thus far, update the UI
if (bestGenome == null ||
ga.CurrentBest.Fitness < bestGenome.Value.Fitness)
{
bestGenome = ga.CurrentBest;
_uiTasks.StartNew(() => txtBestMatch.Text = bestGenome.Value.Text);
// If we've found the solution, bail.
if (bestGenome.Value.Text == _targetText) break;
}
}
// When the task completes, update the UI
}, token).ContinueWith(t =>
{
timerElapsedTime.Stop();
chkParallel.Visible = true;
btnRun.Text = "Start";
_cancellation = null;
switch (t.Status)
{
case TaskStatus.Faulted:
MessageBox.Show(this, t.Exception.ToString(), "Error");
break;
case TaskStatus.RanToCompletion:
txtBestMatch.BackColor = Color.LightGreen;
lblGenerations.BackColor = Color.LemonChiffon;
break;
}
}, _uiTasks.Scheduler);
}
else _cancellation.Cancel();
}
You've probably setup Visual Studio to stop on all thrown exceptions. You can either ignore this (hit continue) or disable this option: Debug menu > Exceptions. Clear the checkbox of "Common Language Runtime Exceptions" Thrown column. Alternatively you can uncheck the specific exception (click the Find button and search for OperationCanceledException).
Playing with Tasks on 4.5 and got the same error but for a different reason.
Posting here as this was the top search result and it took me a while to find the cause.
try
{
await Task.Run(() => DoWork());
label1.Text = "Finished.";
}
catch (OperationCanceledException)
{
label1.Text = "Cancelled.";
}
Which ran:
private async void DoWork()
{
// WORK STUFF
{
workerCancel.Token.ThrowIfCancellationRequested();
}
}
Cancelling would cause the unhandled error because I put void instead of Task:
private async Task DoWork()
The exception was actually handled... To ensure just press F5 to see that is's been caught. To set your debugger not to catch user unhandled exceptions press Ctrl + Alt + E and unselect User-unhandled
Related
I am creating a VSIX project having TextAdornment features. Here when My CreateGeom() method executes, and try to run new Image{};, It throws exception The calling thread must be STA, because many UI components require this. I tried setting ApartmentState manually but no luck. Following is my code:
[STAThread]
internal async void OnLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
{
string lang = getCurruntCodeLanguage();
if (lang.ToString() != "java" && lang.ToString() != "ts" && lang.ToString() != "js")
{
}
else
{
try
{
currentSnapshotText = this.view.TextBuffer.CurrentSnapshot.GetText();
this.currentSnapshotLinesList = this.view.TextBuffer.CurrentSnapshot.GetText().Split('\n');
foreach (string str in this.currentSnapshotLinesList.ToList<string>())
{
TextAdornment1.allLinesList.Add(str.Trim('\r'));
}
if (numberOfLinesBeforeEnter != this.currentSnapshotLinesList.Length)
{
boundstart = 0;
boundend = 0;
this.checkCountIfMarked = 1;
this.markthis.Clear();
if (this.image != null)
{
RemoveMarkedArea();
}
if (threadSendText != null)
{
if (threadSendText.IsAlive)
{
threadSendText.Abort();
}
}
var v = System.Threading.Thread.CurrentThread.GetApartmentState(); //returns 'STA'
threadSendText = new System.Threading.Thread(new ThreadStart(SndTextCall)); // Apartment State is 'Unknown'
threadSendText.SetApartmentState(ApartmentState.STA); // Apartment State is 'STA'
threadSendText.IsBackground = true;
threadSendText.Priority = ThreadPriority.Highest;
threadSendText.Start();
}
numberOfLinesBeforeEnter = this.currentSnapshotLinesList.Length;
}
catch (Exception exc)
{
//MessageBox.Show(exc.ToString());
}
}
}
There are other recursive methods also in SndTextCall(). All are working fine but when CreateGeom() method comes into execution, it throws an exception.
private void CreateGeom(SnapshotSpan span)
{
IWpfTextViewLineCollection textViewLines = this.view.TextViewLines;
this.geometry = textViewLines.GetMarkerGeometry(span);
if (this.geometry != null)
{
this.drawing = new GeometryDrawing(this.brush, this.pen, this.geometry);
this.drawing.Freeze();
var drawingImage = new DrawingImage(this.drawing);
drawingImage.Freeze();
image = new Image
{
Source = drawingImage,
}; // Here the exception comes
Canvas.SetLeft(image, this.geometry.Bounds.Left);
Canvas.SetTop(image, this.geometry.Bounds.Top);
this.drawingImageList.Add(image);
}
}
You can explicitly switch to the UI Thread using the VS Threading Rules or the explanations in the Cookbook for Visual Studio.
private void CreateGeom(SnapshotSpan span)
{
ThreadHelper.JoinableTaskFactory.Run(async delegate
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
// You're now on the UI thread.
// ... Create your image here
});
}
I have code
private void AbrirConexao(string strConexao)
{
try
{
conexao = new NpgsqlConnection(strConexao);
conexao.Open();
}
catch (Exception)
{
ReconectarDB(null, strConexao);
}
}
public bool ReconectarDB(string strConexao)
{
bool erroConexao = false;
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (obj, ea) =>
{
int erro = 0;
while (erro <= 4)
{
Thread.Sleep(1000);
try
{
conexao = new NpgsqlConnection(strConexao);
conexao.Open();
erroConexao = false;
break;
}
catch
{
erro++;
erroConexao = true;
}
}
};
bw.RunWorkerCompleted += (obj, ea) =>
{
if (erroConexao)
DialogReconectando.AlterarTela(ErroConexao.SemConexao);
else
DialogReconectando.Close();
};
bw.RunWorkerAsync();
Application.Current.Dispatcher.Invoke(new Action(() =>
{
if (DialogReconectando == null || Conexao.DialogReconectando.IsLoaded == false)
DialogReconectando = new DialogErroConexao(ErroConexao.Reconectando);
if(DialogReconectando.ShowActivated)
{
DialogReconectando.ShowActivated = true;
DialogReconectando.ShowDialog();
}
}));
return erroConexao;
}
I am using the Open Connection method to connect to the database. and when the connection fails, ReconnectDB is trying to reconnect with the database. If it fails, a Window is opened that there are two buttons, Retry and Abort the System.
The problem is that there are situations that I use other concurrent threads that makes requests with the database. In those cases, I would not want it to display a new Window. So if there is a Window open, I would like the Thread to lock until the Window is closed. I tried to solve the problem using EventWaitHandle. However, Window is also caught in this situation. Would you have any idea how you could solve this problem?
It depends on what you want the second thread to do. If you want the second thread to simply skip over showing the window, you can use a semaphore to ensure that only a single thread shows the window, like this:
SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
private void ShowWindowNonBlocking()
{
bool acquiredLock = false;
try
{
acquiredLock = semaphore.Wait(0);
if (acquiredLock)
{
// This thread now has exclusive access to the isWindowShown variable
var result = MessageBox.Show(
"Retry the connection?",
"Connection Failed",
MessageBoxButtons.RetryCancel);
if (result == DialogResult.Retry)
{
// Retry the connection
}
}
else
{
// Another thread is showing the window
}
}
finally
{
if (acquiredLock)
{
semaphore.Release();
}
}
}
Here is a good site that I refer back to from time to time on locking mechanisms: http://www.albahari.com/threading/part2.aspx#_Semaphore
If however, you want the second thread to block until the first window is finished (for example, if you want to know what the result of the window was in order to know whether to retry on the second thread), you can use a lock, like this:
private object windowLock = new object();
private void ShowWindowBlocking()
{
lock (windowLock)
{
var result = MessageBox.Show(
"Retry the connection?",
"Connection Failed",
MessageBoxButtons.RetryCancel);
if (result == DialogResult.Retry)
{
// Retry the connection
}
}
}
If you need further clarification, let me know and I will try to expand the answer.
To get used to and get trained using Backgroundworker for my Project, i used a sample code which runs smoothly except when it comes to handling error condition it doesn't allow me to use (e.Error!=null) facility of RunWorkerCompletedEventArgs e.I want to handle error like the way cancel and successful completion works for me.
Suggestions please!
Following is the code:
private void DoWork(object sender, DoWorkEventArgs e)
{
Random rand = new Random();
for (int i = 0; i < 10; i++)
{
if (this.backgroundWorker.CancellationPending)
{
e.Cancel = true;
break;
}
// report progress
this.backgroundWorker.ReportProgress(-1, string.Format("Performing step {0}...", i + 1));
// simulate operation step
System.Threading.Thread.Sleep(rand.Next(1000, 10000));
//setting simulateError to true after inducing error(a button)
if (this.simulateError)
{
this.simulateError = false;
//needs a code to use (e.Error!=null) in
RunWorkerCompleted().
//A jump to RunWorkerCompleted is required here.
}
}
}
private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// hide animation
this.pictureBox.Image = null;
// show result indication
if (e.Cancelled)
{
////works nice
this.labelProgress.Text = "Operation cancelled by the user!";
this.pictureBox.Image = Properties.Resources.WarningImage;
}
else
{
//doesn't execute at all....why?
if (e.Error != null)
{
this.labelProgress.Text = "Operation failed: " + e.Error.Message;
this.pictureBox.Image = Properties.Resources.ErrorImage;
}
else
{
//works nice
this.labelProgress.Text = "Operation finished successfuly!";
this.pictureBox.Image = Properties.Resources.InformationImage;
}
}
// restore button states
this.buttonStart.Enabled = true;
this.buttonCancel.Enabled = false;
this.buttonError.Enabled = false;
}
I induce error using simulateError ,for the purpose to show peculiar error message how should i use
if (e.Error != null)
{
this.labelProgress.Text = "Operation failed: " + e.Error.Message;
My Program isn't coming to private void RunWorkerCompleted(object sender, ,RunWorkerCompletedEventArgs e) in case of error. In other cases(cancellation,succesful completion) it executes right.
To get used to and get trained using Backgroundworker for my Project
Why would you do that? Task.Run() is better than BackgroundWorker in every way.
Now to your actual question: to cause an error in a BackgroundWorker, use the standard mechanism for that in .Net: exceptions:
if (this.simulateError)
{
this.simulateError = false;
throw new Exception("Simulating error.");
}
I am using async and await keywords to make an app responsive
I have the following code in the View when the property is raised in the ViewModel.
VIEW: Button Click Event
private async void button1_Click(object sender, RoutedEventArgs e)
{
button1.IsEnabled = false;
// Property Change
_viewModel.Words = await Task.Factory.StartNew(() => File.ReadAllLines("Words.txt").ToList()); // takes time to read about 3 - 4 seconds
switch (_viewModel.RadioButtonWordOrderSelection)
{
case MainWindowViewModel.RadioButtonWordOrderSelections.NormalOrder:
break;
case MainWindowViewModel.RadioButtonWordOrderSelections.ReverseOrder:
await Task.Factory.StartNew(() =>
{
var words = _viewModel.Words.ToList();
words.Reverse();
// Property Change
_viewModel.Words = words;
});
break;
case MainWindowViewModel.RadioButtonWordOrderSelections.Shuffle:
await Task.Factory.StartNew(() =>
{
// Property Change
_viewModel.Words = _viewModel.Words.Shuffle().ToList();
});
break;
}
await Task.Factory.StartNew(() => DownloadSomething(_viewModel.Words)); // takes time to read about 30 - 40 seconds
button1.IsEnabled = true;
}
_viewModel.Progress gets updated in the View
VIEW: Private Method Takes 30 - 40 seconds To Complete
private void DownloadSomething(IEnumerable<string> words)
{
// Property Change
_viewModel.Progress = 0;
foreach (var word in words)
{
// Property Change
_viewModel.Word = word;
try
{
// Some code WebClient download code here
}
catch (Exception e)
{
//Trace.WriteLine(e.Message);
}
// Property Change
_viewModel.Progress++;
}
}
VIEW: Property Change Event Handled
void _viewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
try
{
switch(e.PropertyName)
{
case "Progress":
// Since its a different Thread
// http://msdn.microsoft.com/en-us/magazine/cc163328.aspx
// Sets the Value on a ProgressBar Control.
// This will work as its using the dispatcher
// The following works
//Dispatcher.Invoke(
// DispatcherPriority.Normal,
// new Action<double>(SetProgressValue),
// _viewModel.Progress);
// from http://stackoverflow.com/questions/2982498/wpf-dispatcher-the-calling-thread-cannot-access-this-object-because-a-differen
progress1.Dispatcher.Invoke(
DispatcherPriority.Normal,
new Action(() =>
{
progress1.Value = _viewModel.Progress;
})
);
// This will throw an exception
// (it's on the wrong thread)
//progress1.Value = _viewModel.Progress;
break;
case "Words":
// Since its a different Thread
// http://msdn.microsoft.com/en-us/magazine/cc163328.aspx
// Sets the Max Value on a ProgressBar Control.
// This will work as its using the dispatcher
// The following Works
//Dispatcher.Invoke(
// DispatcherPriority.Normal,
// new Action<double>(SetProgressMaxValue),
// _viewModel.Words.Count);
// from http://stackoverflow.com/questions/2982498/wpf-dispatcher-the-calling-thread-cannot-access-this-object-because-a-differen
progress1.Dispatcher.Invoke(
DispatcherPriority.Normal,
new Action(() =>
{
progress1.Maximum = _viewModel.Words.Count;
})
);
// This will throw an exception
// (it's on the wrong thread)
//progress1.Maximum = _viewModel.Words.Count;
break;
case "Word":
// Since its a different Thread
// http://msdn.microsoft.com/en-us/magazine/cc163328.aspx
// Sets the Contant on a Label Control.
// This will work as its using the dispatcher
// The following Works
//Dispatcher.Invoke(
// DispatcherPriority.Normal,
// new Action<string>(SetLastWordValue),
// _viewModel.Word);
// from http://stackoverflow.com/questions/2982498/wpf-dispatcher-the-calling-thread-cannot-access-this-object-because-a-differen
labelLastWord.Dispatcher.Invoke(
DispatcherPriority.Normal,
new Action(() =>
{
labelLastWord.Content = _viewModel.Word;
})
);
// This will throw an exception
// (it's on the wrong thread)
//labelLastWord.Content = _viewModel.Word;
break;
case "RadioButtonWordOrderSelection":
break;
default:
throw new NotImplementedException("[Not implemented for 'Property Name': " + e.PropertyName + "]");
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
}
}
The UI updates perfectly for the progressBar1 and labelLastWord! I am facing a problem though, when progressBar1 and labelLastWord is updating the rest of the UI is frozen.
Is there a work around to fix this?
I greatly appreciate any help!
I strongly recommend you follow the guidelines in the Task-based Async Programming document. This is far better than just shunting work off to the thread pool via StartNew. If you do have CPU-bound operations, you could use Task.Run, but for everything else, use the existing async-ready endpoints.
Also, I find it useful to treat the entire VM as being in the UI context. So PropertyChanged is always raised in a UI context. Data binding in particular depends on this.
private async Task<List<string>> ReadAllLinesAsync(string file)
{
var ret = new List<string>();
using (var reader = new StreamReader(file))
{
string str = await reader.ReadLineAsync();
while (str != null)
{
ret.Add(str);
str = await reader.ReadLineAsync();
}
}
return ret;
}
private async void button1_Click(object sender, RoutedEventArgs e)
{
button1.IsEnabled = false;
_viewModel.Words = await ReadAllLinesAsync("Words.txt");
List<string> words;
switch (_viewModel.RadioButtonWordOrderSelection)
{
case MainWindowViewModel.RadioButtonWordOrderSelections.NormalOrder:
break;
case MainWindowViewModel.RadioButtonWordOrderSelections.ReverseOrder:
await Task.Run(() =>
{
words = _viewModel.Words.ToList();
words.Reverse();
});
_viewModel.Words = words;
break;
case MainWindowViewModel.RadioButtonWordOrderSelections.Shuffle:
await Task.Run(() =>
{
words = _viewModel.Words.Shuffle().ToList();
});
_viewModel.Words = words;
break;
}
await DownloadSomething(_viewModel.Words);
button1.IsEnabled = true;
}
private async Task DownloadSomething(IEnumerable<string> words)
{
_viewModel.Progress = 0;
foreach (var word in words)
{
_viewModel.Word = word;
try
{
await ...; // async WebClient/HttpClient code here
}
catch (Exception e)
{
//Trace.WriteLine(e.Message);
}
_viewModel.Progress++;
}
}
void _viewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
try
{
switch(e.PropertyName)
{
case "Progress":
progress1.Value = _viewModel.Progress;
break;
case "Words":
progress1.Maximum = _viewModel.Words.Count;
break;
case "Word":
labelLastWord.Content = _viewModel.Word;
break;
case "RadioButtonWordOrderSelection":
break;
default:
throw new NotImplementedException("[Not implemented for 'Property Name': " + e.PropertyName + "]");
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
}
}
As a closing note, I recommend you purchase and read thoroughly Josh Smith's MVVM book. You're using terms like "View" and "ViewModel", but the way you're using these components, you're completely avoiding all the advantages of the MVVM pattern.
The following method is fired when a CD is inserted or ejected.
The problematic code is noted below.
Everything here is based on stepping through the code with breakpoints.
public void CDREventArrived(object sender, EventArrivedEventArgs e)
{
// Get the Event object and display it
PropertyData pd = e.NewEvent.Properties["TargetInstance"];
if (pd != null)
{
ManagementBaseObject mbo = pd.Value as ManagementBaseObject;
if (mbo.Properties["VolumeName"].Value != null)
{
//This line is executed.
textBox1.Text = "test";
//This line is not executed.
//While stepping through the execution,
//I hit F11 on the line above,
//hoping to get to this next line, but it never happens.
//The form pops back up and the step through is complete.
label1.Text = "test";
}
else
{
//Same problem here. Only the first line is hit.
textBox1.Text = "test";
label1.Text = "test";
}
}
}
A related problem is that while it does hit the code to change the text property of textBox1, the text is not actually changed. I can see this on the form and while stepping through breakpoints. So it appears it hits the code, but never actually executes. I'm wondering why it doesn't continue to all the code in the given conditional.
Here is the code which sets up the delegate. This method is called on FormLoad. I stop the listener on form exit.
private void CreateCDRomListener()
{
WqlEventQuery q;
ManagementOperationObserver observer = new
ManagementOperationObserver();
// Bind to local machine
ConnectionOptions opt = new ConnectionOptions();
opt.EnablePrivileges = true; //sets required privilege
ManagementScope scope = new ManagementScope("root\\CIMV2", opt);
try
{
q = new WqlEventQuery();
q.EventClassName = "__InstanceModificationEvent";
q.WithinInterval = new TimeSpan(0, 0, 1);
// DriveType - 5: CDROM
q.Condition = #"TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.DriveType = 5";
w = new ManagementEventWatcher(scope, q);
// register async. event handler
w.EventArrived += CDREventArrived;
w.Start();
// Do something usefull,block thread for testing
Console.ReadLine();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
}
}
My first guess is this callback occurs on a thread that is not the UI thread. Try this:
if (InvokeRequired)
{
Invoke(() => textBox1.Text = "test");
}
else
{
textBox1.Text = "test";
}
I think an exception is being triggered at some point.
I would probably put a try/catch in that code to see if something is triggering an exception.
Is there some event handler for the textbox that's being fired when you attempt to change its Text property that is dumping out early?