(In case you're interested, the background for this question is here, but I don't think it's critical for this particular question.)
We're trying to run a series of report exports (a third party method call) one at a time in separate threads, so we can kill off the thread if it takes too long. The ugly, but best-so-far, idea is to use Thread.Abort to kill the thread exporting a given report, then do a ResetAbort to allow the rest of the code to continue.
The proof of concept code looks like this:
public RunningMethod()
{
Report myReport = new Report();
for (int i = 0; i < 10; i++)
{
Thread reportThread = new Thread(() => DoBackgroundJob(myReport, "test" + i.ToString()));
reportThread.Start();
bool finished = reportThread.Join(TimeSpan.FromMilliseconds(100));
if (!finished)
{
reportThread.Abort();
}
}
}
protected void DoBackgroundJob(Report myReport, string reportFilename)
{
try
{
report.ExportToPdf(#"C:\" + reportFilename + ".pdf");
}
catch (ThreadAbortException)
{
}
break;
}
I'm getting a strange result when I run this...the Export line seems to throw an exception that seems like it should be a ThreadAbortException, but apparently is not, since it doesn't get caught by the catch (ThreadAbortException), but is caught by a catch (Exception).
I'd like to know what kind of exception I'm getting, but I can't see it because when I try to view it I only get "Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack."
Is there a way to determine what is happening? What exception is really being thrown here?
Related
Here is a very strange thing which I don't think should happen:
UnicodeString test = "abc";
try
{
try
{
int a = 123;
return a; // This seems to produce a problem with "test" variable scope
}
catch (Exception &e)
{
// Some exception handler here
}
}
__finally
{
// At this point the "test" variable should still be in scope???
test = "xyz"; // PROBLEM here - test is NULL instead of "abc"! Why?
}
If I remove the return a; in the try-catch block the test variable is still defined. Is there a particular reason why after the above construct the UnicodeString seems to go out of scope? Is it a bug with C++ Builder 2010? I understand that return returns from function but it should still retain variable scope in the __finally block shouldn't it?
I did a bit more analysis and it seams that once you execute return statement all local objects from stack are acting as destroyed. If you try using heap objects instead this won't happen.
UnicodeString *test = new UnicodeString("abc");
try
{
try
{
int a = 123;
return a; // This seems to produce a problem with "test" variable scope
}
catch (Exception &e)
{
// Some exception handler here
}
}
__finally
{
ShowMessage(*test); // "abc"
*test = "xyz";
}
delete test;
Using smart pointers like unique_ptr will again result in loosing an object in __finally since return will initiate it's destruction.
(Remy posted this in comments but did not post an answer here)
When a return statement is hit within a try...finally block, what happens is that any local objects are destroyed (as they would be for any other return) before the __finally block is entered.
So by the time your code gets up to test = "xyz";, test has already been destroyed, causing undefined behaviour.
I guess it is a matter of semantics whether you call this a bug or a design flaw, but either way it is something to bear in mind when using try...finally. My personal advice would be to just not use it at all; the Standard C++ techniques of try...catch and RAII can solve any problem.
Let me setup this question with some background information, we have a long running process which will be generating data in a Windows Form. So, obviously some form of multi-threading is going to be needed to keep the form responsive. But, we also have the requirement that the form updates as many times per second while still remaining responsive.
Here is a simple test example using background worker thread:
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
int reportValue = (int)e.UserState;
label1.Text = reportValue;
//We can put this.Refresh() here to force repaint which gives us high repaints but we lose
//all other responsiveness with the control
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int x = 0; x < 100000; x++)
{
//We could put Thread.Sleep here but we won't get highest performance updates
bw.ReportProgress(0, x);
}
}
Please see the comments in the code. Also, please don't question why I want this. The question is simple, how do we achieve the highest fidelity (most repaints) in updating the form while maintaining responsiveness? Forcing the repaint does give us updates but we don't process windows messages.
I have also try placing DoEvents but that produces stack overflow. What I need is some way to say, "process any windows messages if you haven't lately". I can see also that maybe a slightly different pattern is needed to achieve this.
It seems we need to handle a few issues:
Updating the Form through the non UI thread. There are quite a few solution to this problem such as invoke, synchronization context, background worker pattern.
The second problem is flooding the Form with too many updates which blocks the message processing and this is the issue around which my question really concerns. In most examples, this is handles trivially by slowing down the requests with an arbitrary wait or only updating every X%. Neither of these solutions are approriate for real-world applications nor do they meet the maximum update while responsive criteria.
Some of my initial ideas on how to handle this:
Queue the items in the background worker and then dispatch them in a UI thread. This will ensure every item is painted but will result in lag which we don't want.
Perhaps use TPL
Perhaps use a timer in the UI thread to specify a refresh value. In this way, we can grab the data at the fastest rate that we can process. It will require accessing/sharing data across threads.
Update, I've updated to use a Timer to read a shared variable with the Background worker thread updates. Now for some reason, this method produces a good form response and also allows the background worker to update about 1,000x as fast. But, interestingly it only 1 millisecond accurate.
So we should be able to change the pattern to read the current time and call the updates from the bw thread without the need for the timer.
Here is the new pattern:
//Timer setup
{
RefreshTimer.SynchronizingObject = this;
RefreshTimer.Elapsed += RefreshTimer_Elapsed;
RefreshTimer.AutoReset = true;
RefreshTimer.Start();
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int x = 0; x < 1000000000; x++)
{
//bw.ReportProgress(0, x);
//mUiContext.Post(UpdateLabel, x);
SharedX = x;
}
}
void RefreshTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
label1.Text = SharedX.ToString();
}
Update And here we have the new solution that doesn't require the timer and doesn't block the thread! We achieve a high performance in calculations and fidelity on the updates with this pattern. Unfortunately, ticks TickCount is only 1 MS accurate, however we can run a batch of X updates per MS to get faster then 1 MS timing.
void bw_DoWork(object sender, DoWorkEventArgs e)
{
long lastTickCount = Environment.TickCount;
for (int x = 0; x < 1000000000; x++)
{
if (Environment.TickCount - lastTickCount > 1)
{
bw.ReportProgress(0, x);
lastTickCount = Environment.TickCount;
}
}
}
There is little point in trying to report progress any faster than the user can keep track of it.
If your background thread is posting messages faster than the GUI can process them, (and you have all the symtoms of this - poor GUI resonse to user input, DoEvents runaway recursion), you have to throttle the progress updates somehow.
A common approach is to update the GUI using a main-thread form timer at a rate sufficiently small that the user sees an acceptable progress readout. You may need a mutex or critical section to protect shared data, though that amy not be necessary if the progress value to be monitored is an int/uint.
An alternative is to strangle the thread by forcing it to block on an event or semaphore until the GUI is idle.
The UI thread should not be held for more than 50ms by a CPU-bound operation taking place on it ("The 50ms Rule"). Usually, the UI work items are executed upon events, triggered by user input, completion of an IO-bound operation or a CPU-bound operation offloaded to a background thread.
However, there are some rare cases when the work needs to be done on the UI thread. For example, you may need to poll a UI control for changes, because the control doesn't expose proper onchange-style event. Particularly, this applies to WebBrowser control (DOM Mutation Observers are only being introduced, and IHTMLChangeSink doesn't always work reliably, in my experience).
Here is how it can be done efficiently, without blocking the UI thread message queue. A few key things was used here to make this happen:
The UI work tasks yields (via Application.Idle) to process any pending messages
GetQueueStatus is used to decide on whether to yield or not
Task.Delay is used to throttle the loop, similar to a timer event. This step is optional, if the polling needs to be as precise as possible.
async/await provide pseudo-synchronous linear code flow.
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinForms_21643584
{
public partial class MainForm : Form
{
EventHandler ContentChanged = delegate { };
public MainForm()
{
InitializeComponent();
this.Load += MainForm_Load;
}
// Update UI Task
async Task DoUiWorkAsync(CancellationToken token)
{
try
{
var startTick = Environment.TickCount;
var editorText = this.webBrowser.Document.Body.InnerText;
while (true)
{
// observe cancellation
token.ThrowIfCancellationRequested();
// throttle (optional)
await Task.Delay(50);
// yield to keep the UI responsive
await ApplicationExt.IdleYield();
// poll the content for changes
var newEditorText = this.webBrowser.Document.Body.InnerText;
if (newEditorText != editorText)
{
editorText = newEditorText;
this.status.Text = "Changed on " + (Environment.TickCount - startTick) + "ms";
this.ContentChanged(this, EventArgs.Empty);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
async void MainForm_Load(object sender, EventArgs e)
{
// navigate the WebBrowser
var documentTcs = new TaskCompletionSource<bool>();
this.webBrowser.DocumentCompleted += (sIgnore, eIgnore) => documentTcs.TrySetResult(true);
this.webBrowser.DocumentText = "<div style='width: 100%; height: 100%' contentEditable='true'></div>";
await documentTcs.Task;
// cancel updates in 10 s
var cts = new CancellationTokenSource(20000);
// start the UI update
var task = DoUiWorkAsync(cts.Token);
}
}
// Yield via Application.Idle
public static class ApplicationExt
{
public static Task<bool> IdleYield()
{
var idleTcs = new TaskCompletionSource<bool>();
if (IsMessagePending())
{
// register for Application.Idle
EventHandler handler = null;
handler = (s, e) =>
{
Application.Idle -= handler;
idleTcs.SetResult(true);
};
Application.Idle += handler;
}
else
idleTcs.SetResult(false);
return idleTcs.Task;
}
public static bool IsMessagePending()
{
// The high-order word of the return value indicates the types of messages currently in the queue.
return 0 != (GetQueueStatus(QS_MASK) >> 16 & QS_MASK);
}
const uint QS_MASK = 0x1FF;
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern uint GetQueueStatus(uint flags);
}
}
This code is specific to WinForms. Here is a similar approach for WPF.
I am doing data driven coded UI test. I have given 10 sets of data. It is failing at 5th data set and is stopping. I need Coded UI tests to continue data driven even after failure.
Please suggest me some way to do this.
in your test please use this
Playback.PlaybackSettings.ContinueOnError = true;
Put each set of data in a try-catch block. Catch the error and ignore it or handle it manually, then continue. I assume you pass your data to the UIMap. If so, then something like this:
[TestMethod]
public void Test_Transaction_ID_67890_Test()
{
for (int i = 0; i < testCaseList.Count; i++)
{
try
{
this.UIMap.ClickonManage(testCaseList);
this.UIMap.ClickonAdd(testCaseList);
this.UIMap.SelectAssigned(testCaseList);
this.UIMap.SelectTransactionDateTime(testCaseList);
}
catch (Exception e)
{
TestContext.WriteLine(Got An Error On Iteration " + i.ToString() + ".";
TestContext.WriteLine(e.ToString());
}
}
I am trying to get to grips with C# having not coded for many years and my previous experience being in ANSI C.
I have read a number of books and searched online but one aspect is evading me and I am hoping someone here can help.
In the past I would declare a function and if there was a possibility of something not happening within the function (i.e. file not found etc.) declare the return to be an integer. I would then return 0 if all was well and a value if not. The value would correspond to where the function failed to execute fully and I could branch accordingly from where I called it.
if(function1())
{
// all my error stuff, maybe a switch/case etc.
}
All the examples I have found in C# seem to avoid this technique and I was hoping to get some understanding here.
Thanks in anticipation.
(I know I am a fossil). :)
Exceptions are the approach you use in C# and similar languages.
It goes like this:
try
{
function();
}
catch(FileNotFoundException e)
{
// File not found
}
catch(UnauthorizedAccessException e)
{
// User doesn't have right to access file
}
// etc...
To make this work, function shouldn't return a status code but instead throw an exception in case of an error.
Please note that the exceptions I illustrated in the code block above are thrown by the framework if you try to access a file and one of those errors is happening. So you don't actually have to do this yourself.
Furthermore, in C# there is no implicit conversion from integral values to bool, i.e. if(function()) is invalid, if function returns an int. You would need to write it like this:
if(function() != 0)
{
// all your error stuff
}
There's nothing to stop you doing this (though there are better ways of handling the errors - exceptions for example).
If you do want to carry on with this approach, the biggest problem you are having is that in C# you can't treat an integer as a boolean so your if test won't compile. What you need is:
if (function1() != 0)
{
}
But to check the value you'd need:
int result = function1();
switch (result)
{
case 1:
// Handle this case
break;
case 2:
// Handle this case
break;
default:
// All OK
break;
}
It would be better to return an enumerated type for each error case so that you don't have magic numbers, but exceptions are the way to go:
try
{
function1();
}
catch (SpecificException1 e1)
{
// Handle this case
}
catch (SpecificException2 e2)
{
// Handle this case
}
What you shouldn't have is a general exception handler:
catch (Exception e)
{
}
This just hides other potential problems.
If you want to follow that pattern of checking return value instead of managing errors, you better use enumarations than plain numbers.
For example:
public enum ResultType
{
Error = 0,
Success,
Waiting
}
public ResultType function()
{
if (still_waiting)
return ResultType.Waiting;
if (error_has_occured)
return ResultType.Error;
return ResultType.Success;
}
public void Main()
{
ResultType result = function();
switch (result)
{
case ResultType.Success:
MessageBox.Show("all is good");
break;
case ResultType.Waiting:
MessageBox.Show("still waiting...");
break;
case ResultType.Error:
MessageBox.Show("error has occurred");
break;
}
}
Behind the scenes, it's still using numbers but you put some meaning to each number.
if(function()==1)
{
}
int function()
{
int returnVal =0;
// do stuff
// if true return returnVal =1 else set returnVal =0;
return returnVal;
}
http://msdn.microsoft.com/en-us/library/dd997415.aspx
Per the article referenced above I am trying to handle exceptions in a continuatin task. The example I am citing in the above article is this:
var task1 = Task.Factory.StartNew(() =>
{
throw new MyCustomException("Task1 faulted.");
})
.ContinueWith((t) =>
{
Console.WriteLine("I have observed a {0}",
t.Exception.InnerException.GetType().Name);
},
TaskContinuationOptions.OnlyOnFaulted);
My code is:
Task<string> task = Task<string>.Factory.StartNew(() => process.StartTask(this));
task.ContinueWith(CloseDialog, TaskContinuationOptions.OnlyOnFaulted);
In StartTask, I throw an error just like the example. My expectation is that CloseDialog will execute and I can examine task.Exception within that method as shown by the example. However when I throw the exception I the code simply stops with an unhandled exception. Should I be using a try/catch block? If so, where?
By the way, I want my continuation task (CloseDialog) to ALWAYS run. I'm just using .OnlyOnFaulted because that is what is shown in the example.
A continuation can find out if an exception was thrown by the antecedent Task by the antecedent task's exception property. The following prints the results of a NullReferenceException to the console
Task task1 = Task.Factory.StartNew (() => { throw null; });
Task task2 = task1.ContinueWith (ant => Console.Write(ant.Exception());
If task1 throws an exception and this exception is not captured/queried by the continuation it is considered unhandled and the application dies. With continuations it is enough to establish the result of the task via the Status keyword
asyncTask.ContinueWith(task =>
{
// Check task status.
switch (task.Status)
{
// Handle any exceptions to prevent UnobservedTaskException.
case TaskStatus.RanToCompletion:
if (asyncTask.Result)
{
// Do stuff...
}
break;
case TaskStatus.Faulted:
if (task.Exception != null)
mainForm.progressRightLabelText = task.Exception.InnerException.Message;
else
mainForm.progressRightLabelText = "Operation failed!";
default:
break;
}
}
If you don't use continuations you either have to wait on the task in a try/catch block or query a task's Result in a try/catch block
int x = 0;
Task<int> task = Task.Factory.StartNew (() => 7 / x);
try
{
task.Wait();
// OR.
int result = task.Result;
}
catch (AggregateException aggEx)
{
Console.WriteLine(aggEx.InnerException.Message);
}
Hope this help even if it is a bit late and you know all there is by now! :]