I have a foreach loop that breaks during the loop in the condition of the foreach itself. Is there a way to try catch the item that throws the exception and then continue the loop?
This will run a few times until the exception hits and then end.
try {
foreach(b in bees) { //exception is in this line
string += b;
}
} catch {
//error
}
This will not run at all because the exception is in the condition of the foreach
foreach(b in bees) { //exception is in this line
try {
string += b;
} catch {
//error
}
}
I know some of you are going to ask how this is happening so here is this:
Exception PrincipalOperationException is being thrown because a Principal (b in my example) cannot be found in GroupPrincipal (bees).
Edit: I added the code below. I also figured out that one group member was pointing to a domain that no longer exists. I easily fixed this by deleting the member but my question still stands. How do you handle exceptions that are thrown inside the condition of a foreach?
PrincipalContext ctx = new PrincipalContext(ContextType.domain);
GroupPrincipal gp1 = GroupPrincipal.FindByIdentity(ctx, "gp1");
GroupPrincipal gp2 = GroupPrincipal.FindByIdentity(ctx, "gp2");
var principals = gp1.Members.Union(gp2.Members);
foreach(Principal principal in principals) { //error is here
//do stuff
}
Almost the same as the answer from #Guillaume, but "I like mine better":
public static class Extensions
{
public static IEnumerable<T> TryForEach<T>(this IEnumerable<T> sequence, Action<Exception> handler)
{
if (sequence == null)
{
throw new ArgumentNullException("sequence");
}
if (handler == null)
{
throw new ArgumentNullException("handler");
}
var mover = sequence.GetEnumerator();
bool more;
try
{
more = mover.MoveNext();
}
catch (Exception e)
{
handler(e);
yield break;
}
while (more)
{
yield return mover.Current;
try
{
more = mover.MoveNext();
}
catch (Exception e)
{
handler(e);
yield break;
}
}
}
}
Maybe you can try to create a method like that:
public IEnumerable<T> TryForEach<T>(IEnumerable<T> list, Action executeCatch)
{
if (list == null) { executeCatch(); }
IEnumerator<T> enumerator = list.GetEnumerator();
bool success = false;
do
{
try
{
success = enumerator.MoveNext();
}
catch
{
executeCatch();
success = false;
}
if (success)
{
T item = enumerator.Current;
yield return item;
}
} while (success);
}
and you can use it this way:
foreach (var bee in TryForEach(bees.GetMembers(), () => { Console.WriteLine("Error!"); }))
{
}
Related
I am implementing retry logic for WCF services on the client side.
I have multiple operations in WCF service with various input parameters and return types.
I created a wrapper that can make a call to these certain methods that have no return type(void) using Action delegate. Is there any way to call methods that have various input parameters and return type.
Or is there any logic to implement retry functionality on the client side that can handle multiple WCF services.
Class RetryPolicy<T>
{
public T ExecuteAction(Func<T> funcdelegate,int? pretrycount = null,bool? pexponenialbackoff = null)
{
try
{
var T = funcdelegate();
return T;
}
catch(Exception e)
{
if (enableRetryPolicy=="ON" && TransientExceptions.IsTransient(e))
{
int? rcount = pretrycount == null ? retrycount : pretrycount;
bool? exbackoff = pexponenialbackoff == null ? exponentialbackoff : pexponenialbackoff;
int rt = 0;
for (rt = 0; rt < rcount; rt++)
{
if (exponentialbackoff)
{
delayinms = getWaitTimeExp(rt);
}
System.Threading.Thread.Sleep(delayinms);
try
{
var T = funcdelegate();
return T;
}
catch(Exception ex)
{
if (TransientExceptions.IsTransient(ex))
{
int? rcount1 = pretrycount == null ? retrycount : pretrycount;
bool? exbackoff1 = pexponenialbackoff == null ? exponentialbackoff : pexponenialbackoff;
}
else
{
throw;
}
}
}
//throw exception back to caller if exceeded number of retries
if(rt == rcount)
{
throw;
}
}
else
{
throw;
}
}
return default(T);
}
}
I use above method and make a call
public string GetCancelNumber(string property, Guid uid)
{
RetryPolicy<string> rp = new RetryPolicy<string>();
return rp.ExecuteAction(()=>Channel.GetCancelNumber(property, uid, out datasetarray));
}
I keep getting error "cannot use ref or out parameters in anonymous delegate"
Here is an example of a simple Retry method:
bool Retry(int numberOfRetries, Action method)
{
if (numberOfRetries > 0)
{
try
{
method();
return true;
}
catch (Exception e)
{
// Log the exception
LogException(e);
// wait half a second before re-attempting.
// should be configurable, it's hard coded just for the example.
Thread.Sleep(500);
// retry
return Retry(--numberOfRetries, method);
}
}
return false;
}
It will return true if the method succeed at least once, and log any exception until then.
If the method fails on every retry, it will return false.
(Succeed means completed without throwing an exception in this case)
How to use:
Assuming sample Action (void method) and sample Func (a method with a return type)
void action(int param) {/* whatever implementation you want */}
int function(string param) {/* whatever implementation you want */}
Execute a function:
int retries = 3;
int result = 0;
var stringParam = "asdf";
if (!Retry(retries, () => result = function(stringParam)))
{
Console.WriteLine("Failed in all {0} attempts", retries);
}
else
{
Console.WriteLine(result.ToString());
}
Execute an action:
int retries = 7;
int number = 42;
if (!Retry(retries, () => action(number)))
{
Console.WriteLine("Failed in all {0} attempts", retries);
}
else
{
Console.WriteLine("Success");
}
Execute a function with an out parameter (int function(string param, out int num)):
int retries = 3;
int result = 0;
int num = 0;
var stringParam = "asdf";
if (!Retry(retries, () => result = function(stringParam, out num)))
{
Console.WriteLine("Failed in all {0} attempts", retries);
}
else
{
Console.WriteLine("{0} - {1}", result, num);
}
I'm getting an "Access to modified closure" error in Resharper. Is there a way to pass the task as a parameter to the lambda instead of relying upon a closure?
while (!Quitting && TaskQueue.Any())
{
foreach (var task in TaskQueue.ToArray())
{
if (Quitting || task.Code == TaskCode.Quit)
{
Quitting = true;
return;
}
if (!task.Runnable)
{
continue;
}
var thread = new Thread(() =>
{
try
{
task.Callback();
}
catch (Exception e)
{
if (task.Error != null)
{
task.Error(e);
}
}
});
thread.Start();
}
}
You could use the Thread.Start(object state) method:
while (!Quitting && TaskQueue.Any())
{
foreach (var task in TaskQueue.ToArray())
{
if (Quitting || task.Code == TaskCode.Quit)
{
Quitting = true;
return;
}
if (!task.Runnable)
{
continue;
}
var thread = new Thread(state =>
{
var taskState = (Task)state;
try
{
taskState.Callback();
}
catch (Exception e)
{
if (taskState.Error != null)
{
taskState.Error(e);
}
}
});
thread.Start(task);
}
}
which would have been equivalent to using a separate function:
private void Process(object state)
{
var task = (Task)state;
try
{
task.Callback();
}
catch (Exception e)
{
if (task.Error != null)
{
task.Error(e);
}
}
}
which you would have passed like that:
while (!Quitting && TaskQueue.Any())
{
foreach (var task in TaskQueue.ToArray())
{
if (Quitting || task.Code == TaskCode.Quit)
{
Quitting = true;
return;
}
if (!task.Runnable)
{
continue;
}
new Thread(this.Process).Start(task);
}
}
Sometime you need to run specific code on specific threads, for example winforms. To get the code running on the UI thread you need something like this :
this.BeginInvoke(new MethodInvoker(() =>
{
try
{
//code
}
catch(Exception ex)
{
HandleException(ex);
}
}
SynchornixationContext is another way to do the same thing.
Say that we know that we need to run specific code in the UI thread and we have a given way of handling the exceptions that are thrown on this UI thread(BeginInvoke is not blocking so exceptions will not be transfered). How could we create a method that makes the same thing but simplier like this :
RunOnUIThread(MyMethod);
The RunOnUIThread will contains mor or less the same code as the first example in this code.
Is it possible to create a method like this? And if so How?
You can write some nice extension methods like this
public static class ControlExtension
{
public static IAsyncResult BeginInvokeWithExceptionHandling(this Control control, Action method, Action<Exception> exceptionHandler)
{
if (control == null) throw new ArgumentNullException("control");
if (method == null) throw new ArgumentNullException("method");
if (exceptionHandler == null) throw new ArgumentNullException("exceptionHandler");
return control.BeginInvoke(new MethodInvoker(() =>
{
try
{
method();
}
catch (Exception ex)
{
exceptionHandler(ex);
}
}));
}
public static IAsyncResult BeginInvokeWithExceptionHandling<T>(this Control control, Delegate method, Action<Exception> exceptionHandler, params object[] args)
{
if (control == null) throw new ArgumentNullException("control");
if (method == null) throw new ArgumentNullException("method");
if (exceptionHandler == null) throw new ArgumentNullException("exceptionHandler");
return control.BeginInvoke(new MethodInvoker(() =>
{
try
{
method.DynamicInvoke(args);
}
catch (Exception ex)
{
exceptionHandler(ex);
}
}));
}
}
How to use:
private void HandleException(Exception ex)
{
}
private void MyMethod()
{
}
this.BeginInvokeWithExceptionHandling(MyMethod, HandleException);
Note: Due to Delegate.DynamicInvoke this may be little less performing, you can fix it with strong typed delegate. It is also worth noting that control.BeginInvoke is also internally using Delegate.DynamicInvoke if it can't find what the delegate type is.
public static void InvokeControlAction<t>(t cont, Action<t> action) where t : Control
{
if (cont.InvokeRequired)
{ cont.Invoke(new Action<t, Action<t>>(InvokeControlAction),
new object[] { cont, action }); }
else
{ action(cont); }
}
CodeProject Reference
I ended upp with this based on SriramĀ“s suggestion :
public static void SendToUIThread(Action method, bool UseExceptionHandling = true)
{
if (method == null)
throw new ArgumentNullException("method is missing");
_threadSyncContext.Send(new SendOrPostCallback(delegate(object state)
{
if (UseExceptionHandling)
{
try
{
method();
}
catch (Exception ex)
{
ErrorController.Instance.LogAndDisplayException(ex, true);
}
}
else
method();
}), null);
}
public static void PostOnUIThread(this Control control, Action method, bool UseExceptionHandling = true)
{
if (method == null)
throw new ArgumentNullException("method is missing");
if (control.InvokeRequired)
PostOnUIThread(method, UseExceptionHandling);
else
{
if (UseExceptionHandling)
{
try { method(); }
catch (Exception ex) { ErrorController.Instance.LogAndDisplayException(ex, true); }
}
else
method();
}
}
I have methods that return value/s to the main class. Now, how can I populate a comboBox in the main class using a return value?
public string MapWorkspace(string path)
{
try
{
versionControl = tpc.GetService<VersionControlServer>();
Workspace[] retVal = versionControl.QueryWorkspaces(null, "username", "computername");
foreach (Workspace w in retVal)
{
return w.Name;
}
//var workspace = versionControl.GetWorkspace(path);
}
catch (Exception exception)
{
Log.Write("Failed to map workspace! Exeption: " + exception.ToString());
}
return null;
}
public MainForm()
{
tfs.MapWorkspace(path);
}
I assume you want to return more than 1 value, so in that case you want a return type of IEnumerable<T>
public IEnumerable<string> MapWorkspace(string path)
{
try
{
versionControl = tpc.GetService<VersionControlServer>();
Workspace[] retVal = versionControl.QueryWorkspaces(null, "username", "computername");
foreach (Workspace w in retVal)
{
yield return w.Name;
}
//var workspace = versionControl.GetWorkspace(path);
}
catch (Exception exception)
{
Log.Write("Failed to map workspace! Exeption: " + exception.ToString());
}
return null;
}
and depending of you UI framework you can populate your ComboBox using the same method
Winforms:
foreach(var item in MapWorkspace("mypath"))
{
combobox1.Items.Add(item);
}
Wpf:
MyItems = new ObservableCollection<string>(MapWorkspace("mypath"));
where MyItems is a collection bound to the combobox
I am using asp.net mvc and nhibernate with the unit of work pattern.
I have something like this
public bool IsSomething()
{
unitOfWork.BeginTransaction();
var myGetStuff = repo.GetStuff(1);
if(myGetStuff == null)
{
return false;
}
var somethingElse = myGetStuff.GetSomethingElse();
if(somethngElse == null)
{
return false;
}
return true;
}
So in my if statements if something is null and I need it not to be null I just get out of the statement.
This is opposed as having nested if statements that could be like nested 4 or 5 times to do null checks.
public bool IsSomething()
{
unitOfWork.BeginTransaction();
var myGetStuff = repo.GetStuff(1);
if(myGetStuff != null)
{
var somethingElse = myGetStuff.GetSomethingElse();
if(somethngElse != null)
{
// some more check heere ( could have another few if statements null checks here)
}
}
}
So I find the first way much easier to read then nested levels of if statements.
My problem is that even if you do a query in nhibernate you must wrap it around in a transaction and at the end do either a rollback or commit.
Option 1
public bool IsSomething()
{
unitOfWork.BeginTransaction();
var myGetStuff = repo.GetStuff(1);
if(myGetStuff == null)
{
unitOfWork.Commit();
return false;
}
var somethingElse = myGetStuff.GetSomethingElse();
if(somethngElse == null)
{
unitOfWork.Commit();
return false;
}
unitOfWork.Commit();
return true;
}
This way I don't like as you have to keep putting commit everywhere. If possible I would love to have just one commit(unless I have more than one unit of work transaction)
So then I though why not put it in a finally like this
public bool IsSomething()
{
try
{
unitOfWork.BeginTransaction();
var myGetStuff = repo.GetStuff(1);
if(myGetStuff == null)
{
return false;
}
var somethingElse = myGetStuff.GetSomethingElse();
if(somethngElse == null)
{
return false;
}
return true;
}
catch(Exception ex)
{
unitOfWork.RollBack();
}
finally
{
unitOfWork.Commit();
}
}
I like this but then I realized what happens if the commit fails? It won't rollback and the exception won't be caught.
So anyone else have any ideas?
This code of your looks rather problematic to me, especially when there are nested unit of work calls (how do you handle those?). What I would do is to open the unit of work (and the transactions) in the calling code (the Controller in your case as you use ASP.Net MVC) and not the IsSomething function. It would look something like this:
try
{
unitOfWork.BeginTransaction();
// some code
var isSomething = IsSomeThing()
}
catch(Exception ex)
{
unitOfWork.RollBack();
}
finally
{
unitOfWork.Commit();
}
The IsSomething function would then look simply like this
public bool IsSomething()
{
var myGetStuff = repo.GetStuff(1);
if(myGetStuff == null)
{
return false;
}
var somethingElse = myGetStuff.GetSomethingElse();
if(somethngElse == null)
{
return false;
}
return true;
}