I'm making app with using XF pcl. Even I launched my app on the store already, I'm still newbie in c# world. I'm having a trouble especially using a Thread.
In XF/iOS, I faced after I launched app and took a while(longer than a day), all of Task.Run() of my code does not start new thread. A person advised me if there is a chance that I'm starting many thread and somehow they are not terminated. So new thread's not started.
So I searched my project and I have Task.Run at about 20 places in my code.
I used it when I call 'async Task' method even it background thread is not necessary.
So, I'm going to change it by using 'async void'. But I already changed it like this. and no problem.
Let's say AAAAA() is a 'async Task' method from some nuget library I'm using. So
I can not change method.
void Something()
{
...
Task.Run(async () => await XXXXX.AAAAA());
...
}
to
async void Something()
{
...
await XXXXX.AAAAA();
...
}
But sometimes, I faced that I can't change a method to async easily. So I'm going to change like this at that time.
void Something()
{
...
AA();
...
}
async void AA()
{
await XXXXX.AAAAA();
}
Is this OK unless background thread is not necessary?
I ask this question because I watched lots of videos that saying not to use "Async void".
I wonder if I could use like this if there seems no problem.
Any advice will help me.
Thanks.
Don't do async void. There are several worst practices about it.
Instead, try to solve your threading problems from the root with a good approach to asynchronous programming.
1. Define your task boundaries
Do not just "fire and forget". Expect your task to end and release resources. There are good reasons not to do Task.Run(...) and forget about it.
Async methods exist for a reason. They return in the Future (to quote the Java world). If you fire too many Async task that take long time to complete or get stuck in a loop, you drain your system resources and may end up unable to spawn new tasks.
So analyze your prolem, don't just run random methods from random packages. Design your workflow and identify parallelisms.
A simple straightforward solution is to Task.Run(()=>).Wait(). This destroys all kinds of parallelism but will constrain the resources and, most importantly, adheres with your synchronous programming.
2. A Task is not a Thread
While I discourage the unbounded/uncontrolled use of threads, the truth is that Task.Run(...) won't necessarily spawn new threads. It may not actually do anything under some circumstances.
For example I was forced to do this to force starting a new thread
Task.Factory.StartNew(()=>..., cancellationToken: tokenSource.Token, creationOptions:
TaskCreationOptions.LongRunning, scheduler: TaskScheduler.Default);
TaskCreationOptions.LongRunning tells the Task factory to use an available separate thread. Normally Task.Run runs on the same current thread by exploiting VM waits to run code from other tasks, so as to perform a lightweight context switch. If your synchronous code blocks in a synchronous way the runtime may not give control to other tasks.
3. TPL is made for 2 things
One is responsiveness. If your application is completely asynchronous, then a good use of the TPL leaves your UI thread responsive over waits, e.g. if you click on a button you won't see the whole window greyed and "stuck". This behaviour was introduced by Microsoft to help developers that are unfriendly with proper multithread programming
The other is I/O optimization. If you need to download 5 files, parse a text file from disk and store a bunch of rows in the database you can fire 7 task that leverage the I/O wait times of each task (e.g. SSL handshake, disk buffering, SQL response wait) so that the 7 tasks will reasonably complete by the time of the longest.
If you just invoke asynchronous methods because you found them on your NuGet library you are just doing it wrong, as you may need to invoke the corresponding synchronous version
Summarizing
Your question reveals a lack of understanding of parallel programming. In fact you said you are new to C#. Welcome to the world of .NET.
Parallel programming is not easy, and without a knowledge of your application design it is impossible to help you in a single short answer. You need to take several examples and/or ask questions about specific best practice for some parts of your application by posting real or simil-real code.
Related
I wrote a small computer game where you can mine gold. The game is used to understand asynchronous programming with async and await. The loop menu offers three options: Mine gold, view evaluation, and exit.
The GoldMining method makes heavy use of the CPU. The probability to get one gram of gold during a mining is 1 in 10.000.000. Therefore it takes a long time until 1000g of gold are mined.
You start mining gold asynchronously from the loop menu. Then you can use option 2 (show evaluation) at any time to see the amount of gold you have mined so far.
Although the GoldMining method is very time consuming, the loop menu does not freeze. That's nice. However, I call the asynchronous method GoldMining without await. Now my question: Is this way of calling asynchronous methods to prevent the program from freezing a recommended approach?
//Evaluation contains the gold stock that was mined in total.
//The class definition is done at the very bottom.
Evaluation evaluation = new Evaluation();
await Main(evaluation);
static async Task Main(Evaluation evaluation){
string input="start";
while(input!="exit"){
Console.WriteLine("choose an option:");
Console.WriteLine("1 gold mining");
Console.WriteLine("2 show evaluation");
Console.WriteLine("3 exit.");
input=Console.ReadLine();
switch(input){
//Call GoldMining without await
case "1":GoldMining(evaluation);break;
case "2":Console.WriteLine(evaluation.gold);;break;
case "exit":input="exit"; break;
default:input="exit";break;
}
}
}
static async Task GoldMining(Evaluation evaluation){
Random rand= new Random();
int yield=0;
Console.WriteLine("Gold mining begins");
await Task.Run(() =>
{
while(yield<1000){
int chance =rand.Next(0,10000000);
if(chance==1){yield++;evaluation.gold++;}
} 2
});
Console.WriteLine("1000g Gold minded");
}
public class Evaluation{
public int gold{get;set;}
public Evaluation(){
this.gold=0;
}
}
The game is used to understand asynchronous programming with async and await... The GoldMining method makes heavy use of the CPU.
Asynchronous code is not a natural fit with CPU-bound methods. For CPU-bound methods, you want parallel code or multithreading.
If you want to learn asynchronous code in a more natural way, use an I/O-bound operation. E.g., an HTTP request to https://deelay.me/10000/https://google.com/.
Note that Task.Run is a form of multithreading (pushing work onto the thread pool). So your code is already using both multithreading and asynchrony - which is fine, but complicates things while learning.
However, I call the asynchronous method GoldMining without await. Now my question: Is this way of calling asynchronous methods to prevent the program from freezing a recommended approach?
No, certainly not. This is a kind of "fire and forget", which is dangerous in general. You almost always want to call await; if you do need to spin off a separate "top-level task", then you normally want to capture the task into a local variable and await it later. Otherwise, your app may exit before the operation is complete, and also you may not be aware of any exceptions that have happened.
I'm a bit irritated because I learned from a couple of Youtube videos that the big advantage of asynchronous programming is that the program doesn't freeze while it's handling a complex task.
You're currently writing a Console application. While Console apps are nice for learning most technologies, I believe using Console for learning async is not a good idea. Console apps can be asynchronous, but it's a very unusual environment for asynchronous applications. A much more natural environment is a client app (UI) or a server app (ASP.NET), both of which have framework-level support for asynchrony.
So, when the videos mention not "freezing", they're referring to how await (on a UI app) can keep the UI thread free to handle other messages. Since a Console app doesn't have a UI message loop, the same benefit doesn't apply there. You can build it, but it's way better IMO to learn proper async/await with either a UI app or an ASP.NET app first.
So, first of all your code is not thread safe. You need to use Interlocked.Increment(ref evaluation.gold) instead of evaluation.gold++ and volatile read (or even dummy Interlocked.CompareExchange, see this) at case "2". This may or may not matter, depending on whether your task scheduler is multithreaded or not (it is by default). Well, actually if your scheduler is single threaded then your code wouldn't work at all, due to an infinite loop (adding await Task.Yield(); inside the while loop in Main() would fix that). Either way, the rule of thumb is: always write a thread safe code when doing async.
Now my question: Is this way of calling asynchronous methods to prevent the program from freezing a recommended approach?
Yes, it is a good idea to spawn a background worker, in fact there's no other way to achieve that (I mean, you can spawn a thread instead of async task, but the idea is the same). And no, it is not a good idea to leave it without supervision. What if it fails? You have no option to react to it, even to log an error. What if GoldMining() is called multiple times? Maybe it is allowed, but without limit?
You could keep the result of calling GoldMining() around (without await) and check its status from time to time. You could keep it in a list and disallow too many. But perhaps a better approach would be to have a separate queue, a separate thread/async task that operates on it and also gracefuly handles all the errors. All of that wrapped into a single class.
I'm learning C#/DOTNET as one of the main reasons are incredible speeds over Node.js and OO syntax.
Now the tutorial I am following all of a sudden introduced async, and that's cool, but I could have done that with Node.js as well, so I feel a little disappointed.
My thought was maybe we could take this to the next level with Multithreading, but a lot of questions came up, with discrepancy in the database (like thread one is expecting to get data that thread two updated, but thread two was not executed before thread one retrieved, so thread one is working with an outdated data).
And searching for this seems to return very little information, mostly it's people misunderstanding multithreading and asynchronous programing.
So I'm guessing you would not want to mix API with multithreading?
Yes, it's a thing, and you're already doing it with async tasks.
.NET has a Task Scheduler that assigns your tasks to available threads from the Thread Pool. Default behavior is to create a pool of threads for each available CPU.
Clarification: this doesn't mean 1 task : 1 thread. There's a large collection of work to be done by a number of workers. Scheduler hands a worker a job, worker works until it's done or an 'await' is reached.
From the perspective of a regular async method, it can be hard to see where the 'multi-threading' comes into play. There isn't an obvious difference between Get() and await GetAsync() when your code has to sit and wait either way.
But it's not always about your code. This example might make it more clear.
List<Task> work = new();
foreach(var uri in uriList)
{
work.Add(http.GetAsync(uri));
}
await Task.WhenAll(work);
This code will execute all those GetAsyncs at the same time.
The framework making your API work is doing something similar. It would be pretty silly if the whole server was tied up because a single user requested a big file over dialup.
Async await is used for multi-threading but it is not used only for multi-threading.
I have not pesronally used/seen multi-threading in API but only console jobs. Using TPL in console jobs has improved the efficiency more than 100% for me
Async/Await is powerful and should be used for asynchronic processing in API's too.
Please go through Shiv's videos https://www.youtube.com/watch?v=iMcycFie-nk
I have an async call (DoAsyncWork()), that I would like to start in a fire-and-forget way, i.e. I'm not interesting in its result and would like the calling thread to continue even before the async method is finished.
What is the proper way to do this? I need this in both, .NET Framework 4.6 as well as .NET Core 2, in case there are differences.
public async Task<MyResult> DoWorkAsync(){...}
public void StarterA(){
Task.Run(() => DoWorkAsync());
}
public void StarterB(){
Task.Run(async () => await DoWorkAsync());
}
Is it one of those two or something different/better?
//edit: Ideally without any extra libraries.
What is the proper way to do this?
First, you need to decide whether you really want fire-and-forget. In my experience, about 90% of people who ask for this actually don't want fire-and-forget; they want a background processing service.
Specifically, fire-and-forget means:
You don't care when the action completes.
You don't care if there are any exceptions when executing the action.
You don't care if the action completes at all.
So the real-world use cases for fire-and-forget are astoundingly small. An action like updating a server-side cache would be OK. Sending emails, generating documents, or anything business related is not OK, because you would (1) want the action to be completed, and (2) get notified if the action had an error.
The vast majority of the time, people don't want fire-and-forget at all; they want a background processing service. The proper way to build one of those is to add a reliable queue (e.g., Azure Queue / Amazon SQS, or even a database), and have an independent background process (e.g., Azure Function / Amazon Lambda / .NET Core BackgroundService / Win32 service) processing that queue. This is essentially what Hangfire provides (using a database for a queue, and running the background process in-proc in the ASP.NET process).
Is it one of those two or something different/better?
In the general case, there's a number of small behavior differences when eliding async and await. It's not something you would want to do "by default".
However, in this specific case - where the async lambda is only calling a single method - eliding async and await is fine.
It depends on what you mean by proper :)
For instance: are you interested in the exceptions being thrown in your "fire and forget" calls? If not, than this is sort of fine. Though what you might need to think about is in what environment the task lives.
For instance, if this is a asp.net application and you do this inside the lifetime of a thread instantiated due to a call to a .aspx or .svc. The Task becomes a background thread of that (foreground)thread. The foreground thread might get cleaned up by the application pool before your "fire and forget" task is completed.
So also think about in which thread your tasks live.
I think this article gives you some useful information on that:
https://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx
Also note that if you do not return a value in your Tasks, a task will not return exception info. Source for that is the ref book for microsoft exam 70-483
There is probably a free version of that online somewhere ;P https://www.amazon.com/Exam-Ref-70-483-Programming-C/dp/0735676828
Maybe useful to know is that if your have an async method being called by a non-async and you wish to know its result. You can use .GetAwaiter().GetResult().
Also I think it is important to note the difference between async and multi-threading.
Async is only useful if there are operations that use other parts of a computer that is not the CPU. So things like networking or I/O operations. Using async then tells the system to go ahead and use CPU power somewhere else instead of "blocking" that thread in the CPU for just waiting for a response.
multi-threading is the allocation of operations on different threads in a CPU (for instance, creating a task which creates a background thread of the foreground thread... foreground threads being the threads that make up your application, they are primary, background threads exist linked to foreground threads. If you close the linked foreground thread, the background thread closes as well)
This allows the CPU to work on different tasks at the same time.
Combining these two makes sure the CPU does not get blocked up on just 4 threads if it is a 4 thread CPU. But can open more while it waits for async tasks that are waiting for I/O operations.
I hope this gives your the information needed to do, what ever it is you are doing :)
I'm trying to move some of my old projects from ThreadPool and standalone Thread to TPL Task, because it supports some very handy features, like continuations with Task.ContinueWith (and from C# 5 with async\await), better cancellation, exception capturing, and so on. I'd love to use them in my project. However I already see potential problems, mostly with synchronization.
I've written some code which shows a Producer / Consumer problem, using a classic stand-alone Thread:
class ThreadSynchronizationTest
{
private int CurrentNumber { get; set; }
private object Synchro { get; set; }
private Queue<int> WaitingNumbers { get; set; }
public void TestSynchronization()
{
Synchro = new object();
WaitingNumbers = new Queue<int>();
var producerThread = new Thread(RunProducer);
var consumerThread = new Thread(RunConsumer);
producerThread.Start();
consumerThread.Start();
producerThread.Join();
consumerThread.Join();
}
private int ProduceNumber()
{
CurrentNumber++;
// Long running method. Sleeping as an example
Thread.Sleep(100);
return CurrentNumber;
}
private void ConsumeNumber(int number)
{
Console.WriteLine(number);
// Long running method. Sleeping as an example
Thread.Sleep(100);
}
private void RunProducer()
{
while (true)
{
int producedNumber = ProduceNumber();
lock (Synchro)
{
WaitingNumbers.Enqueue(producedNumber);
// Notify consumer about a new number
Monitor.Pulse(Synchro);
}
}
}
private void RunConsumer()
{
while (true)
{
int numberToConsume;
lock (Synchro)
{
// Ensure we met out wait condition
while (WaitingNumbers.Count == 0)
{
// Wait for pulse
Monitor.Wait(Synchro);
}
numberToConsume = WaitingNumbers.Dequeue();
}
ConsumeNumber(numberToConsume);
}
}
}
In this example, ProduceNumber generates a sequence of increasing integers, while ConsumeNumber writes them to the Console. If producing runs faster, numbers will be queued for consumption later. If consumption runs faster, the consumer will wait until a number is available. All synchronization is done using Monitor and lock (internally also Monitor).
When trying to 'TPL-ify' similar code, I already see a few issues I'm not sure how to go about. If I replace new Thread().Start() with Task.Run():
TPL Task is an abstraction, which does not even guarantee that the code will run on a separate thread. In my example, if the producer control method runs synchronously, the infinite loop will cause the consumer to never even start. According to MSDN, providing a TaskCreationOptions.LongRunning parameter when running the task should hint the TaskScheduler to run the method appropriately, however I didn't find any way to ensure that it does. Supposedly TPL is smart enough to run tasks the way the programmer intended, but that just seems like a bit of magic to me. And I don't like magic in programming.
If I understand how this works correctly, a TPL Task is not guaranteed to resume on the same thread as it started. If it does, in this case it would try to release a lock it doesn't own while the other thread holds the lock forever, resulting in a deadlock. I remember a while ago Eric Lippert writing that it's the reason why await is not allowed in a lock block. Going back to my example, I'm not even sure how to go about solving this issue.
These are the few issues that crossed my mind, although there may be (probably are) more. How should I go about solving them?
Also, this made me think, is using the classical approach of synchronizing via Monitor, Mutex or Semaphore even the right way to do TPL code? Perhaps I'm missing something that I should be using instead?
Your question pushes the limits of broadness for Stack Overflow. Moving from plain Thread implementations to something based on Task and other TPL features involves a wide variety of considerations. Taken individually, each concern has almost certainly been addressed in a prior Stack Overflow Q&A, and taken in aggregate there are too many considerations to address competently and comprehensively in a single Stack Overflow Q&A.
So, with that said, let's look just at the specific issues you've asked about here.
TPL Task is an abstraction, which does not even guarantee that the code will run on a separate thread. In my example, if the producer control method runs synchronously, the infinite loop will cause the consumer to never even start. According to MSDN, providing a TaskCreationOptions.LongRunning parameter when running the task should hint the TaskScheduler to run the method appropriately, however I didn't find any way to ensure that it does. Supposedly TPL is smart enough to run tasks the way the programmer intended, but that just seems like a bit of magic to me. And I don't like magic in programming.
It is true that the Task object itself does not guarantee asynchronous behavior. For example, an async method which returns a Task object could contain no asynchronous operations at all, and could run for an extended period of time before returning an already-completed Task object.
On the other hand, Task.Run() is guaranteed to operate asynchronously. It is documented as such:
Queues the specified work to run on the ThreadPool and returns a task or Task<TResult> handle for that work
While the Task object itself abstracts the idea of a "future" or "promise" (to use synonymous terms found in programming), the specific implementation is very much tied to the thread pool. When used correctly, you can be assured of asynchronous operation.
If I understand how this works correctly, a TPL Task is not guaranteed to resume on the same thread as it started. If it does, in this case it would try to release a lock it doesn't own while the other thread holds the lock forever, resulting in a deadlock. I remember a while ago Eric Lippert writing that it's the reason why await is not allowed in a lock block. Going back to my example, I'm not even sure how to go about solving this issue.
Only some synchronization objects are thread-specific. For example, Monitor is. But Semaphore is not. Whether this is useful to you or not depends on what you are trying to implement. For example, you can implement the producer/consumer pattern with a long running thread that uses BlockingCollection<T>, without needing to call any explicit synchronization objects at all. If you did want to use TPL techniques, you could use SemaphoreSlim and its WaitAsync() method.
Of course, you could also use the Dataflow API. For some scenarios this would be preferable. For very simple producer/consumer, it would probably be overkill. :)
Also, this made me think, is using the classical approach of synchronizing via Monitor, Mutex or Semaphore even the right way to do TPL code? Perhaps I'm missing something that I should be using instead?
IMHO, this is the crux of the matter. Moving from Thread-based programming to the TPL is not simply a matter of a straight-forward mapping from one construct to another. In some cases, doing so would be inefficient, and in other cases it simply won't work.
Indeed, I would say a key feature of TPL and especially of async/await is that synchronization of threads is much less necessary. The general idea is to perform operations asynchronously, with minimal interaction between threads. Data flows between threads only at well-defined points (i.e. retrieved from the completed Task objects), reducing or even eliminating the need for explicit synchronization.
It's impossible to suggest specific techniques, as how best to implement something will depend on what exactly the goal is. But the short version is to understand that when using TPL, very often it is simply unnecessary to use synchronization primitives such as what you're used to using with the lower-level API. You should strive to develop enough experience with the TPL idioms that you can recognize which ones apply to which programming problems, so that you apply them directly rather than trying to mentally map your old knowledge.
In a way, this is (I think) analogous to learning a new human language. At first, one spends a lot of time mentally translating literally, possibly remapping to adjust to grammar, idioms, etc. But ideally at some point, one internalizes the language and is able to express oneself in that language directly. Personally, I've never gotten to that point when it comes to human languages, but I understand the concept in theory :). And I can tell you firsthand, it works quite well in the context of programming languages.
By the way, if you are interested in seeing how TPL ideas taken to extremes work out, you might like to read through Joe Duffy's recent blog articles on the topic. Indeed, the most recent version of .NET and associated languages have borrowed heavily from concepts developed in the Midori project he's describing.
Tasks in .Net are a hybrid. TPL brought tasks in .Net 4.0, but async-await only came with .Net 4.5.
There's a difference between the original tasks and the truly asynchronous tasks that came with async-await. The first is simply an abstraction of a "unit of work" that runs on some thread, but asynchronous tasks don't need a thread, or run anywhere at all.
The regular tasks (or Delegate Tasks) are queued on some TaskScheduler (usually by Task.Run that uses the ThreadPool) and are executed by the same thread throughout the task's lifetime. There's no problem at all in using a traditional lock here.
The asynchronous tasks (or Promise Tasks) usually don't have code to execute, they just represent an asynchronous operation that will complete in the future. Take Task.Delay(10000) for example. The task is created, and completed after 10 seconds but there's nothing running in the meantime. Here you can still use the traditional lock when appropriate (but not with an await inside the critical section) but you can also lock asynchronously with SemaphoreSlim.WaitAsync (or other async synchronization constructs)
Is using the classical approach of synchronizing via Monitor, Mutex or Semaphore even the right way to do TPL code?
It may be, that depends on what the code actually does and whether it uses TPL (i.e. Tasks) or async-await. However, there are many other tools you can now use like async synchronization constructs (AsyncLock) and async data structures (TPL Dataflow)
I've grasped the concept of async await and have been using it sporadically, but do have a couple questions regarding best practices.
is it ok to use await in a while(condition) loop to keep fetching data that may be present, until the while condition changes, e.g. stopProcessingMessages = false.
in an application such as winforms, while UI runs on it's thread, using async/await on an operation such as a button click is fairly trivial, but what about if I would like to enforce asynchronously throughout an entire console application, or even a windows service. what is the best practice to initially kick off that first await task, would that be Task.Run (() => ... )?
I hope I am making sense in my 2nd question. I want to make the most of async and utilize it to it's full extent, but just need to understand how to kick off the initial asynchronous operation before it bubbles down to all other asynchronous functions.
apologies for not using the proper code blocks I am on the train using my smartphone.
I've grasped the concept of async await and have been using it sporadically, but do have a couple questions regarding best practices.
I have an intro to async/await blog post that goes into more detail than most intros and also introduces several best practices.
is it ok to use await in a while(condition) loop to keep fetching data that may be present, until the while condition changes, e.g. stopProcessingMessages = false.
You want to avoid tight loops. So the while (condition) GetDataIfPresent(); is going to consume a lot of CPU.
Alternatively, you could use an async method that returned null (or whatever) if stopProcessingMessages is true. In this case, your code would be while (true), and a more TAP-like solution would be to use CancellationSource instead of a flag.
Also take a look at TPL Dataflow; it sounds like it may be useful for your kind of situation.
console application, or even a windows service. what is the best practice to initially kick off that first await task
For console apps, you could Wait on the top-level task. This is an acceptable exception to the usual guideline (which is to await instead of Wait). Waiting will burn a thread for the duration of the console app, but that's usually not important enough to warrant a more complex solution. If you do want to install a single-threaded context for your console app, you could use AsyncContext.Run from my AsyncEx library.
For Win32 services, you usually do need to start your own thread. You can use Task.Run for this (if you want a multithreaded context), or AsyncContextThread from AsyncEx (if you want a single-threaded context).
Good morning,
I would rather use a regular task with the TaskCreationOption set to 'LongRunning' in your first scenario than the async/await pattern.
This way your whole while block would be executed in one long running task. When using await inside each while loop you would start a new task with every loop - would work, but it's maybe not so optimal ;-)
Regarding your second question, I'm sorry but I don't get your point.
Hope this helps.
It is not ok to use a loop to keep fething data that may be present..
You can create an async call that upon completion will automaticlly invoke a callback method.. the "waiting" phase in that case will happen in the OS mechanisms which treat this waiting phase in optimum way to the OS being used.
Take a look here for further study of the subject:
http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx