Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I want to run GetAnswerToLife method to wait for 5 seconds and then print 210 while "for loop" is printing the numbers. But below code only prints the for loop and I can not make this async method work. 210 is not seen anywhere. Is there anything I am missing here?
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication30
{
internal class Program
{
private static async Task<int> GetAnswerToLife()
{
await Task.Delay(5000);
int answer = 21 * 10;
return answer;
}
private static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine(i);
Thread.Sleep(100);
}
int a = GetAnswerToLife().Result;
Console.WriteLine(a);
}
}
}
It works but they are not working asynchronously. After for loop
finishes printing, after that 210 is printed. What I want it for loop
and other method starts at the same time.
I think you are confusing asynchronous work with parallelism. Asynchronous is doing work , but not blocking the thread , once your thread hit await it actually is released to the thread pool to do some other job, while waiting for the statement after await to evaluate, only after this the execution continues.
Parallelism is where work is done in parallel, hence the name of the action.
Consider this as an example.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class Program
{
private static void Main(string[] args)
{
Parallel.Invoke(PrintLoop, async () => Console.WriteLine(await GetAnswerToLife()));
}
public static void PrintLoop()
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine(i);
Thread.Sleep(100);
}
}
public static async Task<int> GetAnswerToLife()
{
await Task.Delay(5000);
return 21 * 10;
}
}
}
Now 210 will be printed somewhere between numbers 1 and 100, which is different and I think this was what you wanted initially.
#Stephen Cleary explanations about async operations are really off the chart, you should definitely check as a further readings.
You are calling the GetAnswerToLife after the loop. Obviously, it will be executed after the loop.
If you want the answer to life computed in the same time as your loop, call it before the start of the loop:
private static async Task<int> GetAnswerToLife()
{
await Task.Delay(5000);
int answer = 21 * 10;
Console.WriteLine(answer);
return answer;
}
private static void Main(string[] args)
{
var answering = GetAnswerToLife();
for (int i = 0; i < 100; i++)
{
Console.WriteLine(i);
Thread.Sleep(100);
}
// Calling .Result will ensure the answer has been calculated
int a = answering.Result;
}
I also changed your answer to life implementation so it prints the answer in console in order to know the answer when it is done calculating and not at the end of the loop.
Related
This question already has answers here:
'await' works, but calling task.Result hangs/deadlocks
(6 answers)
Closed 3 years ago.
I am following this to get async/await working.
But when I run the below code as debug , it only prints
HandleFile enter
wait...
and then keeps on running , doesn't do anything, it seems to me HandleFileAsync never returns
public async Task method1()
{
Task<int> task = HandleFileAsync();
log.Info("wait...");
task.Wait();
var x = task.Result;
log.Info("print x.."+ x);
}
static async Task<int> HandleFileAsync()
{
string file = #"C:\Users\..\..\text.txt";
log.Info("HandleFile enter");
int count = 0;
// Read in the specified file.
// ... Use async StreamReader method.
using (StreamReader reader = new StreamReader(file))
{
string v = await reader.ReadToEndAsync();
// ... Process the file data somehow.
count += v.Length;
// ... A slow-running computation.
// Dummy code.
for (int i = 0; i < 1000; i++)
{
int x = v.GetHashCode();
if (x == 0)
{
count--;
}
}
}
log.Info("HandleFile exit");
return count;
}
How do I make it run to print x?
Looking at the methods you shared, the async/await looks a little awkward.
deleted the 1st note and changed the void back to Task. Since you are learning, these things are important.
2nd remove the task.wait command, use await. see the changes I have made below.
public async Task method1()
{
log.info('Starting process');
int task = await HandleFileAsync();
log.Info("print x.."+ task);
}
I had ran into the following Getting Started with Async / Await. The blog post is related to Xamarin, but it explain the async/await pattern really well. I hope it helps.
This question already has answers here:
How and when to use ‘async’ and ‘await’
(25 answers)
Call asynchronous method in constructor?
(15 answers)
How Async and Await works
(4 answers)
Closed 4 years ago.
I have a question about both keywords (Async and Await)
Their main goal is to make more than one method to be done at the same time as i understood, so for example if i'm going to do a long task which will prevent the main task from being executed in that case i have to use (Async and Await).
But when I tried it in two different programs that do the same thing i found that the execution is the same w/o using (Async and Await)
first one
class Async
{
public Async()
{
main();
}
public async void main()
{
Console.WriteLine("Main Thread....");
await SlowTask();
Console.WriteLine("Back To Main Thread");
}
public async Task SlowTask()
{
Console.WriteLine("Useless Thread....");
for (int i = 0; i < 1000000; i++)
{
// TODO
}
Console.WriteLine("Finished Useless Thread....");
}
}
and the second
class NoAsync
{
public NoAsync()
{
main();
}
public void main()
{
Console.WriteLine("Main Thread....");
SlowTask();
Console.WriteLine("Back To Main Thread");
}
public void SlowTask()
{
Console.WriteLine("Useless Thread....");
for (int i = 0; i < 1000000; i++)
{
// TODO
}
Console.WriteLine("Finished Useless Thread....");
}
}
the execution of both are exactly the same, from what i understood that when using (Async and Await) both main and SlowTask will execute at the same time without waiting for one to end so the other start to execute but that doesn't happen.
What's wrong i've made or i'm miss-understanding Asynchronous in c# ?
Kind regards.
I'd expect the execution of both to be the same. The issue is the latter, you have a misunderstanding of async in C#.
In short, when you await something in an async method, that thread is freed up to go do other stuff, until the awaited task finishes. But the program does not continue executing the next line until the awaited method completes. That would be bananas. You're thinking more of a background worker.
This can be handy, for example, when you are doing I/O and want a thread to be available to field http requests in the meantime. There is an abundance of reading material on this already. Here is a more in-depth answer
The execution should be exactly the same, they are logically consistent programs. There's likely not even a single task switch given your whole program is merely incrementing a counter variable.
i have a great confusion while working with the async and await.
My logic is simple, i have a method which will cause a delay of 15 seconds, like this
public static Task<int> delay(int num)
{
Task.Delay(15000);
return Task.FromResult(num);
}
now i am calling this method like this
public static async void delayAsync(int num)
{
Console.WriteLine(await delay(num)+"time :"+DateTime.Now);
}
static void Main(string[] args)
{
var details = new details();
Console.WriteLine("## start ##");
for (var i = 0; i < 5; i++)
{
Console.WriteLine("counter: "+i);
delayAsync(i);
}
Console.WriteLine("## finished ##");
Console.Read();
}
my desired output is to get the number one by one after the delay of 15 seconds, but i am getting the results all at once without any pause. am i missing something.
I have gone through this blog and couldnt understand a thing
Here are the steps that you need to achieve this:
Await Task.Delay and return num instead of Task.
public static async Task<int> delay(int num)
{
await Task.Delay(15000);
return num;
}
Make your delayAsync method return Task.
public static async Task delayAsync(int num)
{
Console.WriteLine(await delay(num) + "time :" + DateTime.Now);
}
Wait for the result of the delayAsync in you Main method.
public static void Main(string[] args)
{
Console.WriteLine("## start ##");
for (var i = 0; i < 5; i++)
{
Console.WriteLine("counter: " + i);
delayAsync(i).Wait();
}
Console.WriteLine("## finished ##");
Console.Read();
}
You are not awaiting the Task.Delay
public static async Task<int> delay(int num){
await Task.Delay(15000);
return num;
}
Note that the signature of the method needs to include async. Additionally since you are now using await inside the method, you don't need to explicitly create a Task for the return statement.
Additionally you have to await the delayAsync call in your Main method (note that you cannot make Main async so you have to use a workaround like this: https://stackoverflow.com/a/9212343/868361
my desired output is to get the number one by one after the delay of 15 seconds
When you call an async method that you don't await then the compiler will start it and continue with the rest of the procedures. In your case with the rest of the loop. So the simple solution to get your desired output would be here:
Don't use async methods! Simply make it a serial processing.
To achieve that what you want using async you would have to wait in the loop for the delayAsync method. But this would make the asynchronous processing synchronous and you would end up again in the normal 1 thread serial processing, only having invested a lot of effort to end up from where you started.
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 7 years ago.
Improve this question
Good afternoon everybody.
I am new to Parallel.ForEach and even newer to threading and I wanted to ask your opinion on what is wrong with this code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace MultiThreading_Example
{
class theMeter {
int count1 = 0;
public void CounterMeter()
{
while (this.count1 < 10000)
{
this.count1++;
Console.WriteLine(this.count1);
}
}
}
class Program
{
static void Main(string[] args)
{
theMeter met = new theMeter();
ThreadStart countForMe = new ThreadStart(met.CounterMeter);
for (int i = 0; i < 1000; i++)
{
Thread t1 = new Thread(countForMe);
t1.Start();
t1.Join();
t1.Abort();
}
Console.ReadLine();
}
}
}
Any idea what is wrong with this? I mean, I have tried doing it without t1.Join() and also have tried doing it on one thread. All are at the same speed. How can I get he program to process faster?
Thanks in advance!
Here is sample of working example. The difference is that each thread is stored in list and started in parallel, and then in the end we wait for each thread.
class theMeter
{
private int count1 = 0;
public void CounterMeter()
{
while (this.count1 < 10000)
{
this.count1++;
Console.WriteLine(this.count1);
}
}
}
class Program
{
static void Main(string[] args)
{
theMeter met = new theMeter();
ThreadStart countForMe = new ThreadStart(met.CounterMeter);
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
{
Thread t1 = new Thread(countForMe);
t1.Start();
threads.Add(t1);
}
// here we will wait for completion of every thread that was created and added to list
threads.ForEach(t => t.Join());
Console.ReadLine();
}
}
This code has a couple of issues worth to mention:
Each thread uses the same theMeter instance, so each of them will iterate the same this.count1 variable, so it's not so thread safe. IMO, the better approach is to create own instance for each thread and divide work for each of them. So they won't share the same resources and it won't cause shared resource access issues.
If any of threads will stuck, then your program will freeze. As Join will wait unlimited amount of time for that. If your thread might take a lot of time(network, db, etc), then you can use Join with timeout and then call Abort. But still using of Abort method isn't recommended, as thread should complete his logic in graceful way, not by cruel interruption of Abort method.
In your orignal example you have 1000 threads, and it's too much, as they will fight for CPU resources and might make things much slower. But it will depend on actual things they will do and where bottleneck will be. If this is CPU intensive task, then thread count should be similar to CPUs count. If this they are doing network requests, then it might depend on network bandiwth.
Another way might be using real Parallel.ForEach or Task classes, that can make things a bit easier.
Sample with actual Parallel.ForEach will be like:
class Program
{
static void Main(string[] args)
{
theMeter met = new theMeter();
Enumerable.Range(0, 1000).AsParallel().ForAll((i) => met.CounterMeter());
Console.ReadLine();
}
}
But you won't have so much flexibility here, but it's easier
I had asked question about lock in here and people responded there is no problem in my lock implementation. But i catched problem. Here is same lock implementation and i am getting weird result. I expect to see numbers starts from 1 but it starts from 5.Example is at below.
class Program
{
static object locker = new object();
static void Main(string[] args)
{
for (int j = 0; j < 100; j++)
{
(new Thread(new ParameterizedThreadStart(dostuff))).Start(j);
}
Console.ReadKey();
}
static void dostuff(dynamic input)
{
lock (locker)
{
Console.WriteLine(input);
}
}
}
The code is fine. But you cannot guarantee the order the threads are executed in. When I run the code I get:
0
1
3
5
2
4
6
10
9
11
7
12
8
etc
If you need to run the threads in a specified order, you could look into using ThreadPool.QueueUserWorkItem instead.
class Program
{
static object locker = new object();
static EventWaitHandle clearCount
=new EventWaitHandle(false, EventResetMode.ManualReset);
static void Main(string[] args)
{
for (int j = 0; j < 100; j++)
{
ThreadPool.QueueUserWorkItem(dostuff, j);
}
clearCount.WaitOne();
}
static void dostuff(dynamic input)
{
lock (locker)
{
Console.WriteLine(input);
if (input == 99) clearCount.Set();
}
}
}
It doesn't make sense to put a lock where you're putting it, as you're not locking code which changes a value shared by multiple threads. The section of code you're locking doesn't change any variables at all.
The reason the numbers are out of order is because the threads aren't guaranteed to start in any particular order, unless you do something like #Mikael Svenson suggests.
For an example of a shared variable, if you use this code:
class Program
{
static object locker = new object();
static int count=0;
static void Main(string[] args)
{
for (int j = 0; j < 100; j++)
{
(new Thread(new ParameterizedThreadStart(dostuff))).Start(j);
}
Console.ReadKey();
}
static void dostuff(object Id)
{
lock (locker)
{
count++;
Console.WriteLine("Thread {0}: Count is {1}", Id, count);
}
}
}
You'll probably see that the Thread numbers aren't in order, but the count is. If you remove the lock statement, the count won't be in order either.
You have a couple of problems and wrong assumptions here.
Creating 100 threads in this fashion is not recommended.
The threads are not going to execute in the order they are started.
Placing the lock where you have it will effectively serialize the execution of the threads immediately removing any advantage you were hoping to gain by using threading.
The best approach to use is to partition your problem into separate independent chunks which can be computed simultaneously using only the least amount of thread synchronization as possible. These partitions should be executed on small and fairly static number of threads. You can use the ThreadPool, Parallel, or Task classes for doing this.
I have included a sample pattern using the Parallel.For method. To make the sample easy to understand lets say you have a list of objects that you want to clone and land into a separate list. Lets assume the clone operation is expensive and that you want to parallelize the cloning of many objects. Here is how you would do it. Notice the placement and limited use of the lock keyword.
public static void Main()
{
List<ICloneable> original = GetCloneableObjects();
List<ICloneable> copies = new List<ICloneable>();
Parallel.For(0, 100,
i =>
{
ICloneable cloneable = original[i];
ICloneable copy = cloneable.Clone();
lock (copies)
{
copies.Add(copy);
}
});
}