I have a code that looks a bit like that. I have a method do_it that does the work and uses some resources that must be protected by a mutex. To do it, I tried using a mutex before calling it, to force other tasks to block until the work is done. But the mutex does not block the second task, and both runs in paralell, I would like to know why, and what is the best way to do it.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace teste_threads
{
class test_mutex
{
Mutex mut = new Mutex();
public async Task first()
{
mut.WaitOne();
await do_it();
mut.ReleaseMutex();
}
public async Task second()
{
mut.WaitOne();
await do_it();
mut.ReleaseMutex();
}
public async Task do_it()
{
await Task.Run(() => doSomething());
}
private void doSomething()
{
Console.WriteLine("doSomething starting");
Thread.Sleep(1000);
Console.WriteLine("doSomething ending");
}
}
class Program
{
static test_mutex test = new test_mutex();
static void Main(string[] args)
{
test.first();
Thread.Sleep(100);
test.second();
Thread.Sleep(3000);
}
}
}
I was expecting that the output to this code would be:
doSomething starting
doSomething ending
doSomething starting
doSomething ending
but instead, I get:
doSomething starting
doSomething starting
doSomething ending
doSomething ending
that means the mutex is not blocking when second() is called.
What is wrong with that mutex?
Mutexes - and other synchronous synchronization primitives - cannot be used with asynchronous code. You need asynchronous synchronization primitives.
There is one asynchronous synchronization primitive built-in: SemaphoreSlim, which can be used as an asynchronous mutex as such:
SemaphoreSlim mut = new SemaphoreSlim(1);
public async Task first()
{
await mut.WaitAsync();
try
{
await do_it();
}
finally
{
mut.Release();
}
}
public async Task second()
{
await mut.WaitAsync();
try
{
await do_it();
}
finally
{
mut.Release();
}
}
The problem is that both first and second methods are running in the same thread, so your mutex is basicaly not blocking at all. Try to remove the ReleaseMutex() calls and it will work the same way proving that there are no 2 threads running the code so the Mutex usage is useless.
Related
How do you wait until a function with a task inside is done before continuing?
public void A()
{
Debug.Log("before")
CopyInfoFromDB();
Debug.Log("after")
}
public void CopyInfoFromDB()
{
FirebaseDatabase.DefaultInstance.GetReference(path)
.GetValueAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
Debug.Log("failed");
}
name = ...// loading local varibles from Task.result
});
}
I want it to wait for CopyInfoFromDB to be completed before printing "after". How should I write function A differently?
If you are going to use async-await - be prepared to make all methods involved in pipeline to be asynchronous as well
public async Task A()
{
Debug.Log("before")
await CopyInfoFromDB();
Debug.Log("after")
}
public Task CopyInfoFromDB()
{
return FirebaseDatabase.DefaultInstance
.GetReference(path)
.GetValueAsync();
}
In case GetValueAsync fails, exception will be thrown on the line where you are awaiting for it.
I am trying to generate different objects and insert each object into it's respective List using await and async using the code below:
static List<ClassA> classAList = new List<ClassA>();
static List<ClassB> classBList = new List<ClassB>();
public async void GenerateUsers()
{
await GenerateClassA();
await GenerateClassB();
}
private static Task GenerateClassA()
{
while(true)
{
Thread.Sleep(3000);
classAList .Add(new ClassA());
Console.WriteLine(classAList.Count);
}
}
private static Task GenerateClassB()
{
while (true)
{
Thread.Sleep(6000);
classBList .Add(new ClassB());
Console.WriteLine(classBList.Count)
}
}
When I call GenerateUsers like
UserContainer uc = new UserContainer(); //Class GenerateUsers is defined
uc.GenerateUsers();
Console.WriteLine("Generating.....");
The program does not exit GenerateClassA and Generating..... is not printed to the screen.
How can I generate different objects in an infinite loop using await and async for each infinite loop.
You are using await GenerateClassA();, but GenerateClassA doesn't do anything continuation related - it simply run to completion promising to return a Task. Except: it can't run to completion, because while(true). So yes, this won't work.
Something doesn't become async just beacause you add async. That enables genuinely async operations to be coordinated: nothing more, nothing less.
The methods you are calling are not async, and so they execute synchronously. Indeed, only the first method, GenerateClassA(), is ever even called. That method never returns, so you never get as far as calling the second. Probably you wanted something more like this:
public void GenerateUsers()
{
GenerateClassA();
GenerateClassB();
}
private static async void GenerateClassA()
{
while(true)
{
await Task.Delay(3000);
classAList.Add(new ClassA());
Console.WriteLine(classAList.Count);
}
}
private static async void GenerateClassB()
{
while (true)
{
await Task.Delay(6000);
classBList.Add(new ClassB());
Console.WriteLine(classBList.Count)
}
}
Note that the void return types prevent you from observing the tasks, such as exceptions that might occur. It's not advised. But it's consistent with the code you originally posted.
I have a situation where I must call an async method synchronously, and it is done so as follows:
obj.asyncMethod().Wait(myCancelToken)
If the cancellation token is switched the disposable's within the task will not get disposed despite being activated via a using statement.
The below program illustrates the problem:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace LeakTest {
class Program {
static void Main(string[] args) {
try {
var timeout = new CancellationTokenSource(TimeSpan.FromMilliseconds(100));
LongRunningTask().Wait(timeout.Token);
} catch (OperationCanceledException error) {
// handling timeout is logically okay, but expect nothing to be leaked
}
Console.WriteLine("Leaked Instances = {0}", DisposableResource.Instances);
Console.ReadKey();
}
static async Task LongRunningTask() {
using (var resource = new DisposableResource()) {
await Task.Run( () => Thread.Sleep(1000));
}
}
public class DisposableResource : IDisposable {
public static int Instances = 0;
public DisposableResource() {
Instances++;
}
public void Dispose() {
Instances--;
}
}
}
}
It seems Wait method just kills the task thread on cancellation instead of triggering an exception within that thread and letting it terminate naturally. Question is why?
You've cancelled the task returned by Wait(timeout.Token) not the one returned from LongRunningTask, if you want to cancel that one pass the token to Task.Run and also use await Task.Delay instead of Thread.Sleep and pass the token there as well.
static void Main(string[] args)
{
try
{
var timeout = new CancellationTokenSource(TimeSpan.FromMilliseconds(100));
LongRunningTask(timeout.Token).Wait();
}
catch (AggregateException error)
{
// handling timeout is logically okay, but expect nothing to be leaked
}
Console.WriteLine("Leaked Instances = {0}", DisposableResource.Instances);
Console.ReadLine();
}
static async Task LongRunningTask(CancellationToken token)
{
using (var resource = new DisposableResource())
{
await Task.Run(async () => await Task.Delay(1000, token), token);
}
}
public class DisposableResource : IDisposable
{
public static int Instances = 0;
public DisposableResource()
{
Instances++;
}
public void Dispose()
{
Instances--;
}
}
Note that the using statment will still dispose of the resource once the long running operation finishes. Run this example:
static void Main(string[] args)
{
try {
var timeout = new CancellationTokenSource(TimeSpan.FromMilliseconds(100));
LongRunningTask().Wait(timeout.Token);
} catch (OperationCanceledException error) {
// handling timeout is logically okay, but expect nothing to be leaked
}
Console.WriteLine("Leaked Instances = {0}", DisposableResource.Instances);
Console.ReadKey();
}
static async Task LongRunningTask()
{
using (var resource = new DisposableResource())
{
await Task.Run(() => Thread.Sleep(1000));
}
}
public class DisposableResource : IDisposable
{
public static int Instances = 0;
public DisposableResource()
{
Instances++;
}
public void Dispose()
{
Instances--;
Console.WriteLine("Disposed resource. Leaked Instances = {0}", Instances);
}
}
Output
Leaked Instances = 1
Disposed resource. Leaked Instances = 0
It seems Wait method just kills the task thread on cancellation instead of triggering an exception within that thread
You are incorrect, on when you cancel the only thing that happens is you stop waiting for Wait(myCancelToken) to complete, the task is still running in the background.
In order to cancel the background task you must pass the cancelation token into all of the methods down the chain. If you want the innermost layer (the long running one) to stop early that code must call token.ThrowIfCancellationRequested() throughout its code.
I have a UI which spawns off a background worker thread which performs a complex tree of tasks and sub-tasks that takes about a minute to complete.
A requirement is that the background worker task must be capable of being cancelled once it has begun.
At the moment my solution is naive and makes the code a mess. When a cancel button is pressed in the UI, a cancel token is set. The worker thread periodically (between tasks) polls this token and if it is set, it exits:
void ThreadWorkerHandler(CancelToken cancelToken)
{
DoTask1(cancelToken);
if (cancelToken.IsSet)
return;
DoTask2(cancelToken);
if (cancelToken.IsSet)
return;
DoTask3(cancelToken);
if (cancelToken.IsSet)
return;
DoTask4(cancelToken);
}
void DoTask2(CancelToken cancelToken)
{
DoSubTask2a();
if (cancelToken.IsSet)
return;
DoSubTask2b();
if (cancelToken.IsSet)
return;
DoSubTask2c();
if (cancelToken.IsSet)
return;
}
Is there a better solution? I was toying for something like a SoLongAs statement that would automatically pepper the checks in and automatically and raise an internal exception if the condition was met, which would be internally caught at the end of the loop, eg:
void ThreadWorkerHandler(CancelToken cancelToken)
{
SoLongAs (canelToken.IsSet == false)
{
DoTask1(cancelToken);
DoTask2(cancelToken);
DoTask3(cancelToken);
DoTask4(cancelToken);
}
}
But I imagine that wouldn't work for some reason, also more importantly I doubt something like this actually exists. If not is there a better way to handle this scenario than I am currently using? Thanks.
If you have a collection of delegates that represent your work you can get something that looks pretty close to your code snippet. It has a bit more overhead than your intented syntax, but the key point is that it's a constant overhead, rather than a per-line overhead.
List<Action> actions = new List<Action>()
{
()=> DoTask1(cancelToken),
()=> DoTask2(cancelToken),
()=> DoTask3(cancelToken),
()=> DoTask4(cancelToken),
};
foreach(var action in actions)
{
if (!cancelToken.IsSet)
action();
}
You can use CancellationToken.ThrowIfCancellationRequested(). this will throw exception if token was set.
Also consider using TPL Tasks. All subtasks can be chained one after another with same CancellationToken, this would simplify your code, as TPL framework would take care about checking Token state before invoking continuation.
Your code would looks like this:
Task.Factory.StartNew(DoTask1, cancelationToken)
.ContinueWith(t => DoTask2(), cancelationToken)
.ContinueWith(t => DoTask3(), cancelationToken)
.ContinueWith(t => DoTask4(), cancelationToken)
Note this solution supposing that DoTask<i> will not throw other exceptions except OperationCanceledException.
Note2 you don't have to call ThrowIfCancellationRequested() inside Tasks/subTasks body. TPL will automatically check token state before invoking any continuations. But you can use this method to interrupt execution of task/subtask.
Servy's idea is very good. I'm just stealing it (with all credit to him!) and demonstrating how to use it with an extension method for List<Action>. I'll fully understand anyone that thinks this is "too cute", but I think it has a certain elegance.
Here's an exerpt that show how you can use the extension method. The extension takes a list of Action delegates and runs each one in turn until finished or cancelled, as per Servy's idea.
private static bool test(CancellationToken cancelToken)
{
return new List<Action>
{
doTask1,
doTask2,
doTask3,
doTask4,
() => Console.WriteLine("Press a key to exit.")
}
.Run(cancelToken);
}
And here's the entire sample:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
internal class Program
{
private static void Main(string[] args)
{
CancellationTokenSource cancelSource = new CancellationTokenSource();
Console.WriteLine("Press any key to interrupt the work.");
var work = Task<bool>.Factory.StartNew(() => test(cancelSource.Token));
Console.ReadKey();
cancelSource.Cancel();
Console.WriteLine(work.Result ? "Completed." : "Interrupted.");
}
private static bool test(CancellationToken cancelToken)
{
return new List<Action>
{
doTask1,
doTask2,
doTask3,
doTask4,
() => Console.WriteLine("Press a key to exit.")
}
.Run(cancelToken);
}
private static void doTask1()
{
Console.WriteLine("Task 1 Working...");
Thread.Sleep(1000);
Console.WriteLine("...did some work.");
}
private static void doTask2()
{
Console.WriteLine("Task 2 Working...");
Thread.Sleep(1000);
Console.WriteLine("...did some work.");
}
private static void doTask3()
{
Console.WriteLine("Task 3 Working...");
Thread.Sleep(1000);
Console.WriteLine("...did some work.");
}
private static void doTask4()
{
Console.WriteLine("Task 4 Working...");
Thread.Sleep(1000);
Console.WriteLine("...did some work.");
}
}
public static class EnumerableActionExt
{
public static bool Run(this IEnumerable<Action> actions, CancellationToken cancelToken)
{
foreach (var action in actions)
{
if (!cancelToken.IsCancellationRequested)
{
action();
}
else
{
return false;
}
}
return true;
}
}
}
I'm starting to learn about async / await in C# 5.0, and I don't understand it at all. I don't understand how it can be used for parallelism. I've tried the following very basic program:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Task task1 = Task1();
Task task2 = Task2();
Task.WaitAll(task1, task2);
Debug.WriteLine("Finished main method");
}
public static async Task Task1()
{
await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(5)));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(10)));
Debug.WriteLine("Finished Task2");
}
}
}
This program just blocks on the call to Task.WaitAll() and never finishes, but I am not understanding why. I'm sure I'm just missing something simple or just don't have the right mental model of this, and none of the blogs or MSDN articles that are out there are helping.
I recommend you start out with my intro to async/await and follow-up with the official Microsoft documentation on TAP.
As I mention in my intro blog post, there are several Task members that are holdovers from the TPL and have no use in pure async code. new Task and Task.Start should be replaced with Task.Run (or TaskFactory.StartNew). Similarly, Thread.Sleep should be replaced with Task.Delay.
Finally, I recommend that you do not use Task.WaitAll; your Console app should just Wait on a single Task which uses Task.WhenAll. With all these changes, your code would look like:
class Program
{
static void Main(string[] args)
{
MainAsync().Wait();
}
public static async Task MainAsync()
{
Task task1 = Task1();
Task task2 = Task2();
await Task.WhenAll(task1, task2);
Debug.WriteLine("Finished main method");
}
public static async Task Task1()
{
await Task.Delay(5000);
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Delay(10000);
Debug.WriteLine("Finished Task2");
}
}
Understand C# Task, async and await
C# Task
Task class is an asynchronous task wrapper. Thread.Sleep(1000) can stop a thread running for 1 second. While Task.Delay(1000) won't stop the current work. See code:
public static void Main(string[] args){
TaskTest();
}
private static void TaskTest(){
Task.Delay(5000);
System.Console.WriteLine("task done");
}
When running," task done" will show up immediately. So I can assume that every method from Task should be asynchronous. If I replace TaskTest () with Task.Run(() =>TaskTest()) task done won't show up at all until I append a Console.ReadLine(); after the Run method.
Internally, Task class represent a thread state In a State Machine. Every state in state machine have several states such as Start, Delay, Cancel, and Stop.
async and await
Now, you may wondering if all Task is asynchronous, what is the purpose of Task.Delay ? next, let's really delay the running thread by using async and await
public static void Main(string[] args){
TaskTest();
System.Console.WriteLine("main thread is not blocked");
Console.ReadLine();
}
private static async void TaskTest(){
await Task.Delay(5000);
System.Console.WriteLine("task done");
}
async tell caller, I am an asynchronous method, don't wait for me. await inside the TaskTest() ask for waiting for the asynchronous task. Now, after running, program will wait 5 seconds to show the task done text.
Cancel a Task
Since Task is a state machine, there must be a way to cancel the task while task is in running.
static CancellationTokenSource tokenSource = new CancellationTokenSource();
public static void Main(string[] args){
TaskTest();
System.Console.WriteLine("main thread is not blocked");
var input=Console.ReadLine();
if(input=="stop"){
tokenSource.Cancel();
System.Console.WriteLine("task stopped");
}
Console.ReadLine();
}
private static async void TaskTest(){
try{
await Task.Delay(5000,tokenSource.Token);
}catch(TaskCanceledException e){
//cancel task will throw out a exception, just catch it, do nothing.
}
System.Console.WriteLine("task done");
}
Now, when the program is in running, you can input "stop" to cancel the Delay task.
Your tasks never finish because they never start running.
I would Task.Factory.StartNew to create a task and start it.
public static async Task Task1()
{
await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(5)));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(10)));
Debug.WriteLine("Finished Task2");
}
As a side note, if you're really just trying to pause in a async method, there's no need to block an entire thread, just use Task.Delay
public static async Task Task1()
{
await Task.Delay(TimeSpan.FromSeconds(5));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Delay(TimeSpan.FromSeconds(10));
Debug.WriteLine("Finished Task2");
}
Async and await are markers which mark code positions from where control should resume after a task (thread) completes.
Here's a detail youtube video which explains the concept in a demonstrative manner http://www.youtube.com/watch?v=V2sMXJnDEjM
If you want you can also read this coodeproject article which explains the same in a more visual manner.
http://www.codeproject.com/Articles/599756/Five-Great-NET-Framework-4-5-Features#Feature1:-“Async”and“Await”(Codemarkers)
static void Main(string[] args)
{
if (Thread.CurrentThread.Name == null)
Thread.CurrentThread.Name = "Main";
Console.WriteLine(Thread.CurrentThread.Name + "1");
TaskTest();
Console.WriteLine(Thread.CurrentThread.Name + "2");
Console.ReadLine();
}
private async static void TaskTest()
{
Console.WriteLine(Thread.CurrentThread.Name + "3");
await Task.Delay(2000);
if (Thread.CurrentThread.Name == null)
Thread.CurrentThread.Name = "FirstTask";
Console.WriteLine(Thread.CurrentThread.Name + "4");
await Task.Delay(2000);
if (Thread.CurrentThread.Name == null)
Thread.CurrentThread.Name = "SecondTask";
Console.WriteLine(Thread.CurrentThread.Name + "5");
}
If you run this program you will see that await will use different thread. Output:
Main1
Main3
Main2
FirstTask4 // 2 seconds delay
SecondTask5 // 4 seconds delay
But if we remove both await keywords, you will learn that async alone doesn't do much. Output:
Main1
Main3
Main4
Main5
Main2