Multithreading in c# but variables change too fast - c#

I have a class that executes my function but the variable changes too fast for me to even append my file. I need the speed but I need the functionality in my multithreading. Here's what's in my program.cs that's really the main key in multithreading.
process process = new process();
Thread[] threads = new Thread[15];
static int refInt = 0;
for (int i = 0; i < threads.Count(); i++)
{
threads[i] = new Thread(process.checkCookies);
}
foreach (Thread threadStart in threads)
{
threadStart.Start();
}
That's my program.cs and here's my process library.
public void checkCookies()
{
try
{
while (Interlocked.Increment(ref refInt) < cookies.Count)
{
try
{
string data = functions.cookieToUserId(cookies[refInt]);
if (data == "The cookie is incorrect.")
{
ConsoleWrite("\nThe cookie is invalid.", ConsoleColor.DarkRed);
continue;
}
string cookiesValue = functions.getRobux(cookies[refInt]);
if (cookiesValue == "Invalid cookie.")
{
ConsoleWrite("\nThe cookie is invalid.", ConsoleColor.DarkRed);
continue;
}
else if (Convert.ToInt32(cookiesValue) < 5)
{
ConsoleWrite(string.Format("\nThe account has less than 5 currency. [{0}]", data), ConsoleColor.DarkRed);
continue;
}
else if (Convert.ToInt32(cookiesValue) > 5)
{
ConsoleWrite(string.Format("\nThe account has {0} currency. [{1}]", cookiesValue, data), ConsoleColor.DarkGreen);
functions.appendFile("config/checkedCookies.txt", cookies[refInt]);
continue;
}
}
catch
{
//exception
}
}
}
catch
{
//exception
}
}
My issue is that whenever there is a cookie with a currency integer greater than 5, when it appendsFile which is basically this function here.
public string appendFile(string file, string content)
{
try
{
using (StreamWriter writeStream = File.AppendText(file))
{
writeStream.WriteLine(content);
return "Appended the text successfully!";
}
}
catch (Exception)
{
return "Error appending the text.";
}
}
The refInt changes due to another thread running it. So if refInt is equal to 4, then after it goes through all the else if statements. The refInt changes to 20-25 because of the other threads running the code and changing the global variable so whenever I append text, it appends the wrong cookie. What are some methods to make it so the global variable doesn't get changed too fast, by the way. I need the speed to be as fast as that.

i dont know if its helps or kills ur multithreading idee but did u ever think about mutex lock?
https://www.c-sharpcorner.com/UploadFile/1d42da/threading-with-mutex/

Related

How do prevent a memory leak inside my endless while loop in C#

I am developing a plugin for an application.
The application is calling the plugin when it loads and the plugin start and endless look in this form:
const int sleepTime = 60 * 1000;
while (true)
{
try
{
Thread.Sleep(sleepTime);
//vaProxy.WriteToLog("Invoking checker...", "Green");
Dictionary<string, dynamic> SessionState = vaProxy.SessionState;
Dictionary<string, CallBack> callBacks = vaProxy.SessionState["CallBacks"];
//Checks will only occur in the Pit
if (!Config.IsProcessRunning("Falcon BMS")) continue;
var isJoystickProfileLoaded = vaProxy.GetBoolean("isJoystickProfileLoaded");
bool isProfileLoaded = isJoystickProfileLoaded == true;
if (ConfigFile.IsTrue(vaProxy, "EnableJoystickLoaded") &&
!vaProxy.SessionState["JanJanJoystickIsLoaded"] && !isProfileLoaded)
{
Config.SaySomething("Verify Joystick profile is loaded");
}
if (!SharedMem.GetStatus("isFlying")) continue;
if (ConfigFile.GetEntry(vaProxy, "AutoAVTR") == "True" &&
!SharedMem.GetStatus("isOnGround"))
{
//Check AVTR status
if (!SharedMem.GetStatus("AVTR"))
{
callBacks["SimAVTRSwitchOn"]
.Press(vaProxy, sayWhat: "Start recording", waitAfter: 500);
}
}
if (SessionState.ContainsKey("JanJanIsAutoSave") && !SharedMem.GetStatus("isOnGround"))
{
if (vaProxy.SessionState["JanJanIsAutoSave"])
{
//vaProxy.WriteToLog("Checking save time", "Green");
//save game...
GameIO.SaveGame(vaProxy);
}
}
if (!SessionState.ContainsKey("JanJanIsStatusReport")) continue;
if (vaProxy.SessionState["JanJanIsStatusReport"])
{
Sim.MyStatus(vaProxy);
}
}
catch (Exception ex)
{
vaProxy.WriteToLog("Dynamic Checks\n" + ex.Message, "Red");
Console.Beep();
}
}
vaProxy is a dynamic variable controlled by the sending application.
I suspect that this endless loop is causing a memory leak.
How can I prevent this?
Should I use the using() statement and if yes how?
I can convert the "DO SOME STUFF" to a class, will that help?
I was calling a function not created by be which did not dispose of itself properly.
Placing it in a using(){...} block solved it.

How can I prevent C# and Selenium from exiting code 0

while (1 == 1)
{
int questions = 0;
Thread.Sleep(500);
try
{
driver.FindElement(By.XPath("//*[#id='root']/div/main/div[2]/div/div[1]/button[1]"));
questions++;
}
catch (Exception e)
{
return;
}
try
{
driver.FindElement(By.XPath("//*[#id='root']/div/main/div[2]/div/div[1]/button[2]"));
questions++;
}
catch (Exception e)
{
return;
}
try
{
driver.FindElement(By.XPath("//*[#id='root']/div/main/div[2]/div/div[1]/button[3]"));
questions++;
}
catch (Exception e)
{
return;
}
try
{
driver.FindElement(By.XPath("//*[#id='root']/div/main/div[2]/div/div[1]/button[4]"));
questions++;
}
catch (Exception e)
{
return;
}
if (questions == 0)
{
return;
}
else if (questions == 1)
{
MessageBox.Show("1", "1");
driver.FindElement(By.XPath("//*[#id='root']/div/main/div[2]/div/div[1]/button[1]")).Click();
}
else if (questions == 2)
{
MessageBox.Show("2", "2");
String[] av2 = { "//*[#id='root']/div/main/div[2]/div/div[1]/button[1]",
"//*[#id='root']/div/main/div[2]/div/div[1]/button[2]"};
Random random = new Random();
int a = random.Next(av2.Length);
driver.FindElement(By.XPath(av2[a])).Click();
}
else if (questions == 3)
{
MessageBox.Show("3", "3");
String[] av3 =
{
"//*[#id='root']/div/main/div[2]/div/div[1]/button[1]",
"//*[#id='root']/div/main/div[2]/div/div[1]/button[2]",
"//*[#id='root']/div/main/div[2]/div/div[1]/button[3]"
};
Random random = new Random();
int a = random.Next(av3.Length);
driver.FindElement(By.XPath(av3[a])).Click();
}
else if (questions == 4)
{
MessageBox.Show("4", "4");
String[] av4 =
{
"//*[#id='root']/div/main/div[2]/div/div[1]/button[1]",
"//*[#id='root']/div/main/div[2]/div/div[1]/button[2]",
"//*[#id='root']/div/main/div[2]/div/div[1]/button[3]",
"//*[#id='root']/div/main/div[2]/div/div[1]/button[4]"
};
Random random = new Random();
int a = random.Next(av4.Length);
driver.FindElement(By.XPath(av4[a])).Click();
}
Console.WriteLine(questions + " <");
}
I'm not experienced at all, and don't know why this class keeps exiting with code 0. I've tried multiple things, but none worked. So, what I am trying to have it do is have this piece of C# code check for an xpath with selenium every .5 seconds. but as it is right now, it exits with exit code 0. How can i fix this?
return statement, if placed in the Main function, stops execution of the program. Move your code to function, and add some logic to prevent console application from closing
using System;
namespace ConsoleApp7
{
class Program
{
static void Main(string[] args)
{
DoYourThings();
Console.WriteLine("Press any key to close application...");
Console.ReadKey(); // application hangs here until user clicks any button,
// so you have time to examine console window
}
static void DoYourThings()
{
while (true)
{
try
{
// some code
}
catch (Exception e)
{
Console.WriteLine(e.Message); // output exception message
return; // exits DoYourThings function
}
}
}
}
}
It appears that you want to select a random item from several XPaths (if found) and click it. The problem is that instead of ignoring exceptions (by not doing anything) you're calling return;, which will exit the method.
Instead, you can just remove the return statement from inside your catch blocks, and that should resolve your issue.
Additionally, you seem to have a lot of repeated code which can be simplified if we store some of the results in lists and then loop over those lists (and choose a random element from a list). Also, you only need to initialize the instance of Random once.
For example:
// Only initialize random one time
var random = new Random();
// Store our XPaths in a list so we can loop over them
var buttonXPaths = new List<string>
{
$"//*[#id='root']/div/main/div[2]/div/div[1]/button[1]",
$"//*[#id='root']/div/main/div[2]/div/div[1]/button[2]",
$"//*[#id='root']/div/main/div[2]/div/div[1]/button[3]",
$"//*[#id='root']/div/main/div[2]/div/div[1]/button[4]",
};
// Endless loop
while (true)
{
// Sleep for half a second
Thread.Sleep(500);
// Create a list to hold any WebElements we find
var elements = new List<WebElement>();
// For each XPath, try to find the element and add it to our list
foreach (var buttonXPath in buttonXPaths)
{
try
{
elements.Add(driver.FindElement(buttonXPath));
}
catch
{
// Ignore any exceptions. The next line isn't necessary, but I
// included it so you can see the syntax for explicitly skipping
// a loop iteration and starting it over again (you were using 'return')
continue;
}
}
// If we found any elements. This is the same as: if (elements.Count > 0)
if (elements.Any())
{
// Display the number of elements found in a message box
MessageBox.Show(elements.Count.ToString(), elements.Count.ToString());
// Choose a random element from our list
WebElement randomElement = elements[random.Next(elements.Count)];
// Click it
randomElement.Click();
// This was in your code, not sure why
Console.WriteLine($"{elements.Count} <");
}
}

Waiting for count in rolling time window to go down before executing request

Lets say I have a function that can be started at any given time, and that function sometimes has a lot of requests to do and sometimes a little, but I never want to do more than 20 requests per minute. I do however always want all requests to be executed.
foreach (var user in users)
{
while (requestsInLastMinute < 20)
{
// Waiting for requests to get freed
Thread.Sleep(1000);
}
user.ExecuteRequest();
requestsInLastMinute++;
}
Is there an efficient way to do this, but where the counter only counts the requests done in the last minute?
A simple solution would be this:
var requestsInLastMinute = 0;
var lastMinute = DateTime.Now.Minute;
foreach (var user in users)
{
while (requestsInLastMinute >= 20)
{
if (DateTime.Now.Minute != lastMinute)
{
requestsInLastMinute = 0;
lastMinute = DateTime.Now.Minute;
break;
}
else
{
Thread.Sleep(1000);
}
}
user.ExecuteRequest();
requestsInLastMinute++;
}
A solution based on MemoryCache:
MemoryCache cache = new MemoryCache("my memory cache");
foreach (var user in users)
{
while (cache.Count() >= 20)
{
Thread.Sleep(1000);
}
user.ExecuteRequest();
cache.Add(new CacheItem(Guid.NewGuid().ToString()), new CacheItemPolicy() { AbsoluteExpiration = DateTime.Now.AddMinutes(1) });
}

Cassandra CSharp driver batch statement failing

I am trying to use a batch statement instead of a single binded insert statement.
Even though this is a very small change this fails and I am not looking for a good way for the error handling and to find out which part is the issue. One issue is definetly that the Java API has a getStatements method which is missing in the C# driver.
The pseudo code looks like this:
private BatchStatement batchStatement = new BatchStatement();
private const int blockingFactor = 5;
private int i = 0;
private object locker = new object();
public CassandraBufferHandler()
{
Cluster = Cluster.Builder().AddContactPoints("localhost").Build();
Session = Cluster.Connect("my_keyspace");
InsertStatement = Session.Prepare("Insert into ticks (instrumentcode, timestamp, type, exchange, price, volume) values(?,?,?,?,?,?) if not exists;");
}
public void OnEvent(TickCassandra tickCassandra, long sequence, bool endOfBatch)
{
try
{
lock (locker)
batchStatement.Add(
InsertStatement.Bind(tickCassandra.Instrumentcode,
tickCassandra.Timestamp,
tickCassandra.Type,
tickCassandra.Exchange,
tickCassandra.Price,
tickCassandra.Volume));
if (i++ % blockingFactor == 0)
{
BatchStatement tmp;
lock (locker)
{
tmp = batchStatement;
tmp.EnableTracing();
batchStatement = new BatchStatement();
}
Session.ExecuteAsync(tmp).ContinueWith(t =>
{
if (t.Exception != null)
{
ErrorCount++;
Log.Error(t.Exception.Message + tmp.ToString());
}
else
InsertCount++;
});
}
}
catch (Exception ex)
{
Log.Error("Exception:" + ex);
Active = false;
}

How to pause the "for" loop until getting response

I am using a for loop for making Calls for a list of numbers.
I want to take the first number from the list and make a call and to wait for the response and then proceed to the next number in the list.
I have used AutoResetEvent to do this.But it is not working.
for (int k = 0; k < list_Items.Count; k++) {
Number_To_Call = "9" + list_Items[k].ToString();
phoneCall.Start();
waitingToPickUp.Set(); //AutoReset Event
Thread.Sleep();
waitingToPickUp.WaitOne();
string detector = VoiceDetected;
if (detector == "Machine") {
//code
} else if (detector == "Human") {
//code
} else {
//code
}
}
Code for getting response form the call
void phoneCall_CallStateChanged(object sender, VoIPEventArgs<CallState> e)
{
if (e.Item.IsInCall())
{
phoneCallAudioReceiver.AttachToCall(phoneCall);
phoneCallAudioSender.AttachToCall(phoneCall);
manchineDetector.Start();
waitingToPickUp.Set();
string str = VoiceDetected;
}
else if (e.Item.IsCallEnded())
{
phoneCallAudioReceiver.Detach();
phoneCallAudioSender.Detach();
manchineDetector.Stop();
phoneCall = null;
//Number_To_Call = string.Empty;
InvokeOnGUIThread(() =>
{
Number_To_Call = string.Empty;
});
}
}
Code for Detecting Machine or Human
void manchineDetector_DetectionCompleted(object sender, VoIPEventArgs<AnswerMachineDetectionResult> e)
{
try
{
string VoiceDetected = e.Item.ToString();
}
catch (Exception ex)
{
}
}
Set and immediately WaitOne makes no sense - wait will not need to wait for anything and immediately continue.
Most likely should be reset-call-wait:
waitingToPickUp.Reset();
phoneCall.Start();
waitingToPickUp.WaitOne();

Categories