Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
private async void btnLoadFile_Click(object sender, EventArgs e)
{
if(AccountsFile.ShowDialog()==DialogResult.OK)
{
Accounts = File.ReadAllLines(AccountsFile.FileName);
foreach(string str in Accounts)
{
await LoadAccount(str);
}
}
}
I've ran into a problem, I know how Asynchronous programming works it will wait for the task to be complete but LoadAccount() will never complete because it calls a function with a never ending while loop so it will not reach the next string in Accounts.
I don't know where to start with this problem. Any solutions?
Instead of waiting for each account successively, you could wait for them collectively. This way, even if one of your accounts enters an infinite loop, the others could still proceed to load.
Accounts = File.ReadAllLines(AccountsFile.FileName);
Task completionTask = Task.WhenAll(Accounts.Select(LoadAccount));
You would typically want to store completionTask in a class variable. Subsequently, when you break out of the indefinite while loop within your LoadAccount calls (for example, by signalling cancellation via a polled CancellationToken), you can use this completionTask to wait for all your tasks to complete.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I am creating a bot for a website where the system logs in with several accounts and does a certain action the problem is when it is time to repeat the process example I have 10 accounts and I would like all accounts to do the same process as the first, the accounts are browned in a txt file. What is the correct way to do this?
Sometimes the function runs ahead of time, I'm new to C # I'm studying
My code looping :/
Task.Delay(2000).ContinueWith(t => setMail());
Task.Delay(3500).ContinueWith(t => nextButton());
Task.Delay(5000).ContinueWith(t => setPass());
Task.Delay(6500).ContinueWith(t => logionButton());
Task.Delay(7500).ContinueWith(t => SucessLogin());
You are creating 5 independent tasks which will all run together, rather than one after the other. Instead, just collapse them to one async/await function:
async Task TestStuff(Account account)
{
await Task.Delay(2000);
setMail();
await Task.Delay(3500);
nextButton();
await Task.Delay(5000);
setPass();
await Task.Delay(6500)
logionButton();
await Task.Delay(7500);
SucessLogin();
}
You mentioned that you've got accounts stored in a file. In this example you'll need to create an Account class and populate it with the information you get from the file. For example:
List<Account> accounts = LoadAccounts("some-file.txt")
foreach(var account in accounts)
{
await TestStuff(account);
}
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
My first non-async attempt was to use a timer to call the process every 15 seconds. This quickly created multiple processes running which started a race condition on the database because the function _myApp.ProcessQueue(); could take 5-10 minutes to run based on the size of the queue. This actually locked up the database because it was trying to read and write to the same rows. If I increase the timer it would prevent the potential for a race condition but I don't think that's a very pragmatic way to go about this service.
protected override void OnStart(string[] args)
{
_log.Info($"Service is started at {DateTime.Now}.");
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 15000;
timer.Enabled = true;
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
int recCount = _dbHandler.CheckQueueCount();
if (recCount > 0)
{
_log.Info($"Found {recCount} records in the queue.");
try
{
_myApp.ProcessQueue();
}
catch (Exception exception)
{
_log.Error(exception);
Stop();
}
}
}
I'm thinking the way to go about this is to use an asynchronous function but I'm having trouble getting that written since I haven't used .Net's async capabilities before.
Use the OnStart() to initialize your runner in an other thread (Task.Run() or if you have to tune some parameters Task.Factory.Start()) to have a proper return of the method within short time.
If I understand you correctly, you only want to process one job at a time and after that you want to process the next one, right?
My examples include always to wait for additional 15s. If you don't want this, you have to adjust the code a little bit.
Without async/await
To synchronize your loop with your job processing, you can start the job in another thread (see above) and use a AutoResetEvent. In your loop you gonna wait with _autoResetEvent.WaitOne() and as soon as your job has been done you can signal with _autoResetEvent.Set() the other thread to continue.
Use something appropriate to wait for the 15s like Thread.Sleep()
With async/await
It's much easier, you only have to await your task call.
await Task.Run(() => MyJobMethod(argA, argB, ...));
await Task.Delay(15000);
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I making an Experiment, I have a loop of 100000 increments and inside it there is a thread that does a specific task(write a log to DB), my question is when I run it its finish in one second maybe and it start to insert them lately, then how the OS handles them and it will process them all or will skip from them?
I try awaited method with them its good. but I want to know what will happen if this code was on a server and received 100000 requests.
The Code:
for (int i = 0; i < 100000; i++)
{
Task.Run(() => log.WriteToLog(i + "", new Models.CustomerModel.CustomerModel()));
}
I am not looking for alternative ways, I need to know the behaviour and how this code handles in OS (if there is a queue, some of them will run, etc..)
PS: I know its not a good approach
1 second is a bit quick. I suspect you are not logging 100000 entries properly and entries are being lost.
Assuming that code was the only code inside say a console app's main(), then because you don't await any of the tasks, it is entirely possible your process is exiting before the logging is complete.
Change:
Task.Run(() => log.WriteToLog(i + "",
new Models.CustomerModel.CustomerModel()));
...to:
await Task.Run(() => log.WriteToLog(i + "",
new Models.CustomerModel.CustomerModel()));
Also, as ckuri mentions in the comments, spawning a great deal of tasks in a tight loop probably isn't a good idea. Consider batching the logging or using IOCP.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I cant seem to find the information that im looking for in the documentation and could use a second pair of eyes. I would like to do this without testing; only a visual examination and theory discussion.
My draft attempt sets a bool which will only allow an async method to be run if the returned task sets its value to Task.IsCompleted. My question is, will this code do what I assume it will and if not, what is an alternative that will perform only a single call at a time? (assuming the infinite loop and async task remain unchanged)
You may fairly assume that RunAsync() is an asynchronous method, denoted by the async keyword, containing an awaitable task which returns a Task instance.
bool asyncOutputCallAllowed = true;
while (true)
{
if (asyncOutputCallAllowed)
{
asyncOutputCallAllowed = false;
asyncOutputCallAllowed = RunAsync().IsCompleted;
}
}
I am guessing that you are trying to do the following: make an async call, keep looping and doing other stuff while also waiting for async-task to finish, and then start a new async task when the previous one finishes. If so, then you probably want something along the following lines:
Task activeOperation = null;
while (true)
{
if (activeOperation == null)
{
// No async operation in progress. Start a new one.
activeOperation = RunAsync();
}
else if (activeOperation.IsCompleted)
{
// Do something with the result.
// Clear active operation so that we get a new one
// in the next iteration.
activeOperation = null;
}
// Do some other stuff
}
Depending on your exact algorithm, you might want to start the new task in the same iteration in which the previous one finishes. That is just a small tweak of the above.
If you are not doing anything else in the loop except wait for the async-task, then you can get rid of the loop entirely and use a continuation instead (see ContinueWith).
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
In my WebApi project I have an endpoint that should delay a small block of code.
Let's make an example:
I need to implement a mechanism that permit the client to book for a resource. The booking time should only have a duration of 120 seconds and then expire.
In terms of code I have something like this:
//booking
foreach (var item in list) {
item.Status = ItemStatus.Booked;
}
await _context.SaveChangesAsync();
//Setup a delayed "thread" which removes the booking
Task.Delay( TimeSpan.FromMinutes( 2 ) )
.ContinueWith( x => {
//loop on the list and set the status to "ReadyForSale"
//if this is still in the Booking
} );
return;
I would like to understand if a solution like this satisfy my requirement. The current thread should not be blocked from the delayed task and I need to find a way to pass the list of items to the delayed task.
I think there is a risk that the task will never run. What if the sever crashes or IIS decides it needs to recycle the pool.
There is the risk that the state would never be restored.
I would probably set a bokedAt DateTime field in the database and then check if that time compared to now is more than two minutes to determine if the item is booked or not. Perhaps even a computed column that checks this and returns the state.