Lock based on a flag - c#

I want to lock few lines of code based on a flag from App config. So based on that flag I run the application asynchronously or not. So i need to lock execution of few lines of code by checking the flag. So i need to write code repetitive. Below is the sample
if (flag) {
lock(dataLock){
//few lines of code
}
} else {
//repeat the above code gain here (few lines of code)
}
Is there any alternative way where I can save my repeated codes.

if (flag)
Monitor.Enter(dataLock);
// few lines of code
if (Monitor.IsEntered(dataLock))
Monitor.Exit(dataLock);

Use Monitor.Enter instead of Lock() {} ? Enter and exit with the if statement.

You could call a function with your outsourced code from within the lock and even from within the else statement. That would at least reduce your overhead and repetitive code.
if(flag==true){
lock(dataLock){
fewLines();
}
}else{
fewLines();
}
[...]
public void fewLines(){
// put your few lines here.
}
that would run the function from the locked context.

The Monitor.Enter aproach is best, but you could also do this:
Action fewLinesOfCode = () =>
{
//few lines of code
};
if (flag)
{
lock (dataLock)
{
fewLinesOfCode();
}
}
else
{
fewLinesOfCode();
}

Related

Loop either not working or never ending c#

Im trying to learn loops and they are on the verge of breaking me. This loop has either not worked at all or never ended which has lead to some serious stress. If anyone could help me out it would be great. The plan is for the loop to continue until someone writes yes/Yes/YES (any form of yes preferably) and then break and continue the next part of the code which is some readlines and write lines, haven't gotten that far because the loop hasn't let me yet. Very thankful for any input.
Console.WriteLine("Hello Inspector!");
Console.WriteLine("Are you ready to identify the suspects? Just write yes and we'll get started.");
string Start = Console.ReadLine();
Startup();
while (Start.Contains("")==false)
{
Console.WriteLine("Just type yes when you are ready.");
if (Start.Contains("Yes") == true)
Console.WriteLine("Let's start.");
break;
}
}
static void Startup()
{
string Start = Console.ReadLine();
if (Start.Contains("yes") == true)
{
Console.Clear();
Console.WriteLine("Here are the suspects:");
}
else
{
Console.WriteLine("Just type yes when you are ready.");
}
}
}
}
There are several issues with your code:
1) You only once read user input - as m.sh already noted, you need to put
Start = Console.ReadLine();
inside your while loop.
2) Your break you expect only to catch if your condition is met is outside the scope because you are missing enclosing { } like this:
if (Start.Contains("Yes") == true)
{
Console.WriteLine("Let's start.");
break;
}
3) Not directly a programming bug but widely frowned upon: explicitly comparing boolean. Simply use
if (Start.Contains("yes"))
instead of
if (Start.Contains("yes") == true)
4) Also already mentioned - use .ToLower() to allow any input casing
if (Start.ToLower().Contains("yes"))
will work for yes, YES, yEs, YeS, ...
Putting together the parts for a working loop
// many coding guidelines ask you to use string.Empty rather than "". [I.]
string Start = string.Empty;
while (!Start.ToLower().Contains("yes"))
{
Console.WriteLine("Just type yes when you are ready.");
Start = Console.ReadLine();
}
Console.WriteLine("Let's start.");
Note the negation ! for the while condition - this makes your loop run as long as the condition is not met instead of having to check inside your loop if you need to break out.
Another way to loop could be do { } while(); where your condition is checked at the end of the loop:
string Start = string.Empty;
do
{
Console.WriteLine("Just type yes when you are ready.");
Start = Console.ReadLine();
}
while (!Start.ToLower().Contains("yes"));
If you step through your code running in debugger, you will notice the different behavior and how do {} while() can be considered faster code than while() { }.
I. In C#, should I use string.Empty or String.Empty or “” to intitialize a string?

Jump to certain line in code C#

I have a few methods that are called from within a few other methods. When in some of the methods a certain action is performed, I would like to go back to the very first method and skip the rest of the code. At the moment, I use booleans to check the "status" of the program but I would like to avoid this because the methods should be void since in essence they don't need to return anything. I found stuff like goto but that only works in the same method.
Question: is there a way to jump to a specific point in the code in a different method in C#? I found stuff on other languages but not a lot on C#.
Current situation:
void test1()
{
bool status = test2();
if (!status)
return; // the other stuff will not get done
Debug.WriteLine("Initialization OK");
}
bool test2()
{
bool status = test3();
if (!status)
return false; // the other stuff will not get done
// do other stuff
return true;
}
bool test3()
{
if (xxx)
return false; // the other stuff will not get done
else
// do other stuff
return true;
}
Wanted situation:
void test1()
{
test2();
// do other stuff
Debug.WriteLine("Initialization OK");
GOTOHERE:
Debug.WriteLine("Initialization NOT OK");
}
void test2()
{
test3();
// do other stuff
}
void test3()
{
if (xxx)
**GOTOHERE**; // Go directly to the location in test1() so that all unnecessary code is skipped
// do other stuff
}
I was surprised to learn that C# does actually support a GOTO command. But it is designed to allow exit from deep nested loops.
This article explains it and gives lots of examples: https://www.dotnetperls.com/goto
However
Unless you are still coding in 1970 then using GOTO is considered very bad practice. It makes code maintenance very difficult. And it even causes problems and performance issues, and makes life for the JIT compiler more difficult.
The go to statement as it stands is just too primitive, it is too much
an invitation to make a mess of one's program.
Edsger W. Dijkstra
Returning something from your method to indicate what you should do afterwards is exactly what you should do. Thus return a boolean indicating if test2 or test3 succeeded and use that value to indicate if you want to proceed further. Don´t use goto nowadays as it only leeds to spaghetti-code, that is hard to maintain. To determine under which circumstances control-flow should jump to GOTOHERE you´d need to scan your entire code for that specific goto-statement.
In your case you want to indicate if some initialization-code works correct. Thus you can also throw an exception:
void test3()
{
if (xxx)
throw new Exception("Some text");
// do other stuff
}
This way you don´t need to return anything from your method, but handle the exception appropriately:
void test1()
{
try { test2(); }
catch {
// some exception-handling such as logging
return;
}
Debug.WriteLine("Initialization OK");
}
This has the advantage that you don´t need to check in test2 if test3 succeeded, allowing you to let the exception bubble through your methods until it is finally handled by a catch. If no catch was found in the entire callstack your app will probably terminate.
C# does have the goto keyword, which works just like in other languages. Declare a label as label_you_want_to_jump_to:, and use goto label_you_want_to_jump_to (https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/goto).
Now that this is said, it is usually a bad idea to use goto, especially in such a way. Your problem might be solved more easily by refactoring a bit. Splitting test3 into two functions, reducing the amount of nesting might be such a way. You may also throw an exception in test3, and catch it in test1. It all depends on what you want to do.
If you get rid of the explicit bools (which are redundant), your (rather contrived) example looks a lot "cleaner" in my opinion:
void test1()
{
if (test2())
{
Debug.WriteLine("Initialization OK");
}
}
bool test2()
{
return test3();
}
bool test3()
{
return xxx;
}
I also prefer to use positive rather than negative conditions, so "if (true)" rather than "if (!false)". This avoids double negatives, which are harder to understand.
Effectively we are using Predicate Logic. We can combine our predicates (methods than return bool without side effects) using the normal logic operators. Consider this example:
bool test4()
{
if (test1())
{
if (test2())
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
We note that this is simply a logical conjunction (and) of test1 and test2, so can simply use the && conjunction operator to make this much clearer:
bool test4()
{
return test1() && test2();
}
Similarly for logical disjunction (or):
bool test5()
{
if (test1())
{
return true;
}
else if (test2())
{
return true;
}
else
{
return false;
}
}
We can write this instead as:
bool test5()
{
return test1() || test2();
}
I don't recommend it, but the simple answer to your question is to use a goto statement.
See: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/goto
You should, however, really be returning values from previous method calls that you can use to determine if you need to run other code.
You can also throw exceptions, but in general I'm not a fan of using them for control of flow unless the circumstance is exceptional (hence the name, I suppose). If you expect that control may flow this way or that, it is not exceptional.
I do understand your point but breaking the sequence of events (aka jumping) is not good practice. Your code becomes unreadable because the reader needs to jump from one place to another. There is a reason why you can't jump out of the current method:
What follows is a really simplified explanation. I am glosing over many details.
If you have knowledge about how the stack works you'll know that the runtime will push a new stack frame onto the stack for each new method invocation. That new stack frame contains the method's local variables as well as other things that are implementation details. If you want to jump to another method the runtime would need to push a new stack frame onto your stack in order to create those local variables for that method. So your goto would become a method invocation rather than a jump statement. Which is weird and not what you/we want. Use normal method invocations in such scenarios rather than jump statements.
There are widly accepted jumping statements like return, break and continue. goto is not one of them, although I consider goto case to be a valid solution in some cases.
Returning the information about what to do next is the correct behaviour here.
I do agree that returning a bool is not very expressive from a sematic perspective, at least not whith your current method names. Naming improvement suggestion:
void DoTest1();
bool TryTest2();
bool TryTest3();
FYI
bool flag;
void test1()
{
test2();
if (flag) {
// do other stuff
Debug.WriteLine("Initialization OK");
}
else {
Debug.WriteLine("Initialization NOT OK");
}
}
void test2()
{
test3();
if (flag) {
// do other stuff
}
}
void test3()
{
if (xxx)
return;
// do other stuff
flag = true;
}

C# lock internal implementation

I know that now in C# lock is implemented in such way:
bool lockWasTaken = false;
var temp = obj;
try
{
Monitor.Enter(temp, ref lockWasTaken);
{
//body
}
}
finally
{
if (lockWasTaken)
{
Monitor.Exit(temp);
}
}
Why do we need this: var temp = obj; ?
Simple, What if you changed the variable after the Monitor.Enter called and before Monitor.Exit?
To prevent that it takes up a copy of the variable. Even you can set the value to null also inside the lock statement but still it makes sure that it releases the lock which it taken earlier.
Because obj might be reassigned within the body of the lock code, and the code you've shown has to make sure that it calls Exit on the same object it called Enter for.

Monitor.TryEnter for multiple resources

I tried searching for this but did not find the suggestion best suited for the issue that I am facing.
My issue is that we have list/stack of available resources (Calculation Engines). These resources are used to perform certain calculation.
The request to perform the calculation is triggered from an external process. So when the request for calculation is made, I need to check if any of the available resources are currently not performing other calculations, If so wait for some time and check again.
I was wondering what the best way to implement this is. I have the following code in place, but not sure if it is very safe.
If you have any further suggestions, that will be great:
void Process(int retries = 0) {
CalcEngineConnection connection = null;
bool securedConnection = false;
foreach (var calcEngineConnection in _connections) {
securedConnection = Monitor.TryEnter(calcEngineConnection);
if (securedConnection) {
connection = calcEngineConnection;
break;
}
}
if (securedConnection) {
//Dequeue the next request
var calcEnginePool = _pendingPool.Dequeue();
//Perform the operation and exit.
connection.RunCalc(calcEnginePool);
Monitor.Exit(connection);
}
else {
if (retries < 10)
retries += 1;
Thread.Sleep(200);
Process(retries);
}
}
I'm not sure that using Monitor is the best approach here anyway, but if you do decide to go that route, I'd refactor the above code to:
bool TryProcessWithRetries(int retries) {
for (int attempt = 0; attempt < retries; attempt++) {
if (TryProcess()) {
return true;
}
Thread.Sleep(200);
}
// Throw an exception here instead?
return false;
}
bool TryProcess() {
foreach (var connection in _connections) {
if (TryProcess(connection)) {
return true;
}
}
return false;
}
bool TryProcess(CalcEngineConnection connection) {
if (!Monitor.TryEnter(connection)) {
return false;
}
try {
var calcEnginePool = _pendingPool.Dequeue();
connection.RunCalc(calcEnginePool);
} finally {
Monitor.Exit(connection);
}
return true;
}
This decomposes the three pieces of logic:
Retrying several times
Trying each connection in a collection
Trying a single connection
It also avoids using recursion for the sake of it, and puts the Monitor.Exit call into a finally block, which it absolutely should be in.
You could replace the middle method implementation with:
return _connections.Any(TryProcess);
... but that may be a little too "clever" for its own good.
Personally I'd be tempted to move TryProcess into CalcEngineConnection itself - that way this code doesn't need to know about whether or not the connection is able to process something - it's up to the object itself. It means you can avoid having publicly visible locks, and also it would be flexible if some resources could (say) process two requests at a time in the future.
There are multiple issues that could potentially occur, but let's simplify your code first:
void Process(int retries = 0)
{
foreach (var connection in _connections)
{
if(Monitor.TryEnter(connection))
{
try
{
//Dequeue the next request
var calcEnginePool = _pendingPool.Dequeue();
//Perform the operation and exit.
connection.RunCalc(calcEnginePool);
}
finally
{
// Release the lock
Monitor.Exit(connection);
}
return;
}
}
if (retries < 10)
{
Thread.Sleep(200);
Process(retries+1);
}
}
This will correctly protect your connection, but note that one of the assumptions here is that your _connections list is safe and it will not be modified by another thread.
Furthermore, you might want to use a thread safe queue for the _connections because at certain load levels you might end up using only the first few connections (not sure if that will make a difference). In order to use all of your connections relatively evenly, I would place them in a queue and dequeue them. This will also guarantee that no two threads are using the same connection and you don't have to use the Monitor.TryEnter().

is there a better way to handle RPC_E_CALL_REJECTED exceptions when doing visual studio automation?

this is what I'm currently doing:
protected void setupProject()
{
bool lbDone = false;
int liCount = 0;
while (!lbDone && liCount < pMaxRetries)
{
try
{
pProject.ProjectItems.Item("Class1.cs").Delete();
lbDone = true;
}
catch (System.Runtime.InteropServices.COMException loE)
{
liCount++;
if ((uint)loE.ErrorCode == 0x80010001)
{
// RPC_E_CALL_REJECTED - sleep half sec then try again
System.Threading.Thread.Sleep(pDelayBetweenRetry);
}
}
}
}
now I have that try catch block around most calls to the EnvDTE stuff, and it works well enough. The problem I have is when I to loop through a collection and do something to each item once.
foreach(ProjectItem pi in pProject.ProjectItems)
{
// do something to pi
}
Sometimes I get the exception in the foreach(ProjectItem pi in pProject.ProjectItems) line.
Since I don't want to start the foreach loop over if I get the RPC_E_CALL_REJECTED exception I'm not sure what I can do.
Edit to answer comment:
Yes I'm automating VS from another program and yes I usually am using VS for something else at the same time. We have an application that reads an xml file then generates around 50 VS solutions based on the xml file. This usually takes a couple of hours so I try to do other work while this is happening.
There is a solution on this MSDN page: How to: Fix 'Application is Busy' and 'Call was Rejected By Callee' Errors. It shows how to implement a COM IOleMessageFilter interface so that it will automatically retry the call.
First, Hans doesn't want to say so but the best answer to "how to do this" is "don't do this". Just use separate instances of visual studio for your automation and your other work, if at all possible.
You need to take your problem statement out somewhere you can handle the error. You can do this by using in integer index instead of foreach.
// You might also need try/catch for this!
int cProjectItems = pProject.ProjectItems.Length;
for(iProjectItem = 0; iProjectItem < cProjectItems; iProjectItem++)
{
bool bSucceeded = false;
while(!bSucceeded)
{
try{
ProjectItem pi = pProject.ProjectItems[iProjectItem];
// do something with pi
bSucceeded = true;
}catch (System.Runtime.InteropServices.COMException loE)
{
liCount++;
if ((uint)loE.ErrorCode == 0x80010001) {
// RPC_E_CALL_REJECTED - sleep half sec then try again
System.Threading.Thread.Sleep(pDelayBetweenRetry);
}
}
}
}
I didn't have much luck with the recommended way from MSDN, and it seemed rather complicated. What I have done is to wrap up the re-try logic, rather like in the original post, into a generic utility function. You call it like this:
Projects projects = Utils.call( () => (m_dteSolution.Projects) );
The 'call' function calls the function (passed in as a lambda expression) and will retry if necessary. Because it is a generic function, you can use it to call any EnvDTE properties or methods, and it will return the correct type.
Here's the code for the function:
public static T call<T>(Func<T> fn)
{
// We will try to call the function up to 100 times...
for (int i=0; i<100; ++i)
{
try
{
// We call the function passed in and return the result...
return fn();
}
catch (COMException)
{
// We've caught a COM exception, which is most likely
// a Server is Busy exception. So we sleep for a short
// while, and then try again...
Thread.Sleep(1);
}
}
throw new Exception("'call' failed to call function after 100 tries.");
}
As the original post says, foreach over EnvDTE collections can be a problem as there are implicit calls during the looping. So I use my 'call' function to get the Count proprty and then iterate using an index. It's uglier than foreach, but the 'call' function makes it not so bad, as there aren't so many try...catches around. For example:
int numProjects = Utils.call(() => (projects.Count));
for (int i = 1; i <= numProjects; ++i)
{
Project project = Utils.call(() => (projects.Item(i)));
parseProject(project);
}
I was getting the same error using C# to read/write to Excel. Oddly, it worked in debug mode but not on a deployed machine. I simply changed the Excel app to be Visible, and it works properly, albeit about twice as slow. It is annoying to have an Excel app open and close dynamically on your screen, but this seems to be the simplest work-around for Excel.
Microsoft.Office.Interop.Excel.Application oApp = new ApplicationClass();
oApp.Visible = true;
oApp.DisplayAlerts = false;

Categories