How can implement awaiting manually? - c#

As an example suppose we have this:
public class MyClass
{
public async Task<bool?> MySynchronousNonBlockingFunction()
{
await here ...
return MyDialogResult;
}
}
and caller must call my function as below:
public async void Button_Click()
{
var instance = new MyClass();
var result = await instance.MySynchronousNonBlockingFunction();
if (result == true)
{
some work ...
}
}
But using Task for awaiting as a such, forces you to make your MySynchronousNonBlockingFunction() function async. And as a side effect you must call MyClass.MySynchronousNonBlockingFunction() only inside an async void to be worked as expected.
I think it is not well for the caller. Because a lazy developer in an application development team may call MySynchronousNonBlockingFunction() without await and then application will not works fine. I want handle this async operation in my code internally and not to the caller. To prevent this development mistakes. same as this one:
public void Button_Click()
{
var instance = new MyClass();
var result = instance.MySynchronousNonBlockingFunction();
if (result == true)
{
some work ...
}
}
In fact, i not want freeze the running thread by wait nor actually pause thread so it must be free to process other its works in another call stack again. Witch i want is actually same as the work of await keyword for a Task execution. is there another option to make this use? and what is your solution here to implement await behavior?
I know there is in c# some ways to lock an object full-fanced and force the execution stack to wait. (for example by using Monitor, or Mutex etc). And all the ways that i found in c# are blocking the running thread.
But, How can i implement awaiting manually? Is there another way to achieve this purpose?

In fact, i want pause ui thread from continue executing at a position, and then resume it again to continue execution in later (from CallStack snapshot position). But i not want freeze or actually pause therad so it must be free to process other its works in another call stack again. Witch i want is actually same as the work of await keyword for a Task execution. is there another option to make this use?
That's not how await works, though. await works by returning and then resuming just that method later. In particular, the call stack is not captured.
If you want to mess around with switching thread stacks, then check out fibers. However, there are no .NET bindings for the fiber APIs, and it's quite possible that a lot of .NET code will simply break if you try to use fibers instead of threads. Then there's the whole question of whether a fiber can actually be an STA context for UI elements; I'm really not sure about that one. In short, here be dragons.
and what is your solution here?
Well, a modal dialog - by definition - is supposed to block other dialogs and run a nested message loop.
If you don't want this behavior, then write modeless dialogs instead. I.e., call Show instead of ShowDialog.

GUI window handlers are message-driven state-machines. You must write code that reflects that. That means no, you cannot sanely just wait, and you should not try.

Related

Fire and forget, using `Task.Run` or just calling an async method without `await`

Note: This a question for outside of the realm of Asp.Net and web apps.
In general especially when it comes to libraries or console apps, in order to fire and forget an async method, is it better to just call the async method without awaiting it or use Task.Run?
Basically:
public static void Main(){
// Doing
_ = DoSomethingAsync();
// vs.
_ = Task.Run(DoSomethingAsync);
}
private static async Task DoSomethingAsync()
{
...
}
In general especially when it comes to libraries or console apps, in order to fire and forget an async method, is it better to just call the async method without awaiting it or use Task.Run?
In general, it's best not to use fire-and-forget at all.
"Fire and forget" means:
You don't care if the code has an exception. Any exceptions will cause it to fail silently; no logging, no notification, etc.
You don't need to know when the code completes. I.e., the consuming application doesn't ever need to wait for the code to complete. Even during shutdown.
You don't need the code to complete. As a corollary of (2), fire-and-forget code may not run to completion; and as a corollary of (1), you would have no notification that it failed to complete.
In short, "fire and forget" is only appropriate for an extremely small number of tasks. E.g., updating a cache. I'd say probably 85% or more of "fire and forget" code is wrong - it's using fire and forget for code that should not be fire and forget.
So I'd say the best solution is to not use fire and forget at all. At the very least, you should expose a Task somewhere that represents a "followup action". Consider adding the Task to your return type or exposing it as a property.
Adopting fire and forget - especially in a library - means you're forcing all consumers to never know when it's safe to shut down and exit. But if you really want to do fire and forget, there are a few options.
A. One option is calling an async void function without a context. The consuming application still has no way to determine if/when the code completes, but at least that way exceptions are not ignored.
B. Another option is to start the task without a context. This option has both disadvantages of fire and forget code: exceptions are ignored and the calling code cannot know when it completes.
Both of these recommendations start the task without a context. There are helpers for doing this, or you can wrap the call in Task.Run (slightly less efficient, but it works fine).
I wouldn't recommend starting the task directly. While this would work fine in a Console app, it's not appropriate for libraries which may be called in situations where a context is provided.
In general, it depends but Task.Run is the safer choice and the reasoning behind it depends on two things:
If we can guarantee that the async method is always going to be asynchronous. Guaranteeing a method to be always asynchronous can become especially tricky for library projects or if the async method is in a code that is not managed by the caller. For example once I had implemented method similar to this example in a library:
public async Task HandleMessages(Func<Task> onMessageNotification)
{
while(true)
{
var msg = MessagingClient.ReceiveMessage();
...
if(msg.MessageType == "MakeAPizza")
{
_ = onMessageNotification();
_ = MakePizzaAsync();
}
}
}
private async Task MakePizzaAsync() {...}
I wanted to fire and forget onMessageNotification and MakePizzaAsync since I didn't want it to hold up the message handling. What I didn't catch was when the caller implementedonMessageNotification like below:
Func<Task> onMsgNotification = () => {
DoSlowOperation();
return Task.CompletedTask;
}
Which would practically made the onMessageNotification synchronous operation, and had to wait on the DoSlowOperation() to finish. So in order to avoid to fix issue I just had to change it to:
_ = Task.Run(onMessageNotification);
_ = MakePizzaAsync();
We won't have long running operations in the async method before the first await operation. The other way that the caller can cause issues is if onMsgnotification Func were implemented in the following way:
Func<Task> onMsgNotification = async () => {
DoSlowOperation();
await AsyncOperation();
}
Which would have still slowed down the HandleMessages method because DoSlowOperation is still getting called synchronously.

Call an awaitable method inside a Thread in C#

In my C# 7.0 Code I like to use an old school Thread of type Thread to do some work. Inside this Thread, I need to use some async methods. What would be the best approach to call these methods?
Writing the thread function async does not make any sense.
this._networkListenerThread = new Thread(/* async here is not an option */() =>
{
while (!this._listenerCancellation.IsCancellationRequested)
{
try
{
// This does not compile
var packetBuffer = await this._commProxy.ReadAsync();
doSomethingMore();
}
}
}
If we go down the call stack, finally there will be this call:
// _socket is of type Android.Bluetooth.BluetoothSocket
// .InputStream of type System.IO.Stream
// ReadAsync only returns when data arrived on the stream
// or throws an exception when the connection is lost
var receivedBytes = await this._socket.InputStream.ReadAsync(buffer, 0, buffer.Length);
For those wondering why I want to use a Thread instead of Task: I want to give it a meaningful name to enhance debugging. I did not find a way to name a Task. Besides of this, this Thread runs almost as long as the application runs, therefore a Thread does make sense for me.
this Thread runs almost as long as the application runs
No, it doesn't. Because the work that it's doing is asynchronous. The thread runs long enough to check the status of the cancellation token, fire off ReadAsync (which, being asynchronous, will return basically immediately) and then it's done. The thread goes away, and it has no more work to do. That's the whole idea of asynchronous operations; being asynchronous means the operation returns to its caller pretty much immediately, and does whatever meaningful work it has to do after returning control back to the caller (in this case, since this is the top level method of the thread, returning control back means that the thread has finished executing and gets torn down).
So there just isn't much of any purpose in creating a new thread just to have it check a boolean value and start some operation that will go off and do work on its own. It's not that you should use a different way of getting a new thread to do work (like using Task.Run), but rather you shouldn't use any means of getting a new thread to do work, because you don't have any long running CPU bound work to do. The long running (non-CPU bound, by the look of it) work that you have is already asynchronous, so you can just call the method directly from whatever thread wants to start this work, and have it do it right in line.
If you simply want to have some value that you can share along an asynchronous operation's logical call context, there are of course tools that accomplish that, such as AsyncLocal. Creating a new thread wouldn't accomplish that, because as you finish starting the asynchronous operation you have your thread is dead and gone, and the continuations will be running in some other thread anyway.

AutoResetEvent.WaitOne() cause deadlock

I'm writing a application with a critical region.
And I decide to use AutoResetEvent to achieve mutual exclusion.
Here's the code
public class MyViewModel
{
private AutoResetEvent lock = new AutoResetEvent(true);
private aync Task CriticalRegion()
{
Dosomething();
}
public async Task Button_Click()
{
Debug.WriteLine("Entering Button_Click");
lock.WaitOne();
try
{
await CriticalRegion();
}
finally
{
lock.Set();
Debug.WriteLine("Leaving Button_Click");
}
}
}
I have a button whose click event calls the Button_Click() method
It works normally. But, if I'm quick enough to click the button for another time before the first call to Button_Click() completes, the whole app stops responding.
In the Debug window I find something like this
Entering Button_Click
Entering Button_Click
Looks like the method never completes.
I struggled a bit and find that if I change lock.WaitOne(); to
if (!sync.WaitOne(TimeSpan.FromSeconds(1)))
{
return;
}
In this case my app is able to avoid the deadlock,but I don't know why it works.
I only know about the IPC from my OS course and the async and await pattern in C#, and I'm not so familiar with the thread in .Net world.
I really want to understand what's really going on behind the scenes.
Thanks for any replys ;)
You have a deadlock because WaitOne is blocking the main thread (button click handler is executed on the main thread), while you haven't called ConfigureAwait(false) when calling await, which means that it tries to run the code which is after await on the main thread, even if it's blocked, which would causes a deadlock.
I suggest reading this post for a thorougher explanation of the dead lock situation.
For your code, I would suggest putting the lock deeper, probably within the async Task, and trying to use a more suitable pattern for locking, preferably, the lock statement, because using Event objects is awkward for mutual exclusion, as Hans stated in the comment.
AutoResetEvent.WaitOne() will block infinitely until you call AutoResetEvent.Set(), which you never seem to do except for after the WaitOne() call.
Quoting the AutoResetEvent.WaitOne() documentation:
Blocks the current thread until the current WaitHandle receives a signal.

AsyncAwait causes unexpected method behavior, Methods runs in wrong thread if called from constructor

I'm trying to do some time consuming actions without freezing the GUI Thread. The UpdateSomething Method is called in two places once in the constructor of my ViewModel and once on button click (RelayCommand). The Method is executed in a WorkerThread if the method is called via RelayCommand, but runs in the MainThread (GUI) when the method call comes from the constructor.
What causes this strange behavior? I double check a few times via IntelliTrace.
This is the method in question:
private async void UpdateSomething()
{
var item = await Task.Factory.StartNew(() =>this.DoSomething("I should run async"));
this.TestItem = item;
}
I'm using WPF and .Net 4.5
For the case where the Tasks action runs on the main thread, the most likely cause is that the method UpdateSomething is being called from within another Task (a Task that was scheduled to run on the main thread). In that case, the TaskScheduler.Current is the main thread TaskScheduler not the TaskScheduler.Default which queues work to the thread pool.
Task.Factory.StartNew defaults to using TaskScheduler.Current (you can change what it uses by calling the appropriate override), while Task.Run uses TaskScheduler.Default.
The statement that Task.Factory.StartNew doesn't play will with async/await is not correct, it's just that some of the defaults are probably not what you want for the common case (this is part of whyTask.Run was introduced).
See:
http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx
Why is TaskScheduler.Current the default TaskScheduler?
I ran into the same problem a while ago. I stuck up a little post about it here:
Today I had a major hair pulling moment. I was using a await/async on a block of code wrapped in a new task. No matter what I did it would just start the Task but then not wait for the result.
After much frustration I worked out that using await Task.Factory.StartNew doesn't play well with await.
In the end I simply changed it to Task.Run what was then worked fine.
Basically you need to use Task.Run instead because await doesn't play nicely with Task.Factory.StartNew
This question was answered by #Rene147 but he deleted his answer. (for whatever reason)
I will briefly rephrase what he had written:
await/asycn doesn't play very well with Task.Factory.StartNew().
Simply replace Task.Factory.StartNew by Task.Run and everything should work:
private async void UpdateSomething()
{
//not working when call comes from constructor
//var item = await Task.Factory.StartNew(() =>this.DoSomething("I should run async"));
//working
var item = await Task.Run(() =>this.DoSomething("I run async!"));
this.TestItem = item;
}
Rene147 also wrote a short blogpost about it.
Would be happy to get more information about this issue, still seems odd to me.

Why does the file async API block

I am writing a simple metro app. However, the API blocks when accessing files. By blocking, I mean the programs waits forever. Creating/opening a file or folder should take at most a few seconds. In this case, it takes forever.
When I run the program, it never comes back from OnTest. Is it what you get.
I understand .Wait will wait for the creation of files and folders to finishe. Maybe that's not great design. However, that's not the point.
My question is:
Do you get the same behavior (blocks the program forever)
Is it what's supposed to happen or is it a bug in WinRT? (I am using the consumer preview)
If that's the expected behavior, why does it take forever?
Here is the XAML code:
<Button Click="OnTest">Test</Button>
Here is the C# code:
private async void OnTest(object sender, RoutedEventArgs e)
{
var t = new Cache("test1");
t = new Cache("test2");
t = new Cache("test3");
}
class Cache
{
public Cache(string name)
{
TestRetrieve(name).Wait();
}
public static async Task TestRetrieve(string name)
{
StorageFolder rootFolder = ApplicationData.Current.LocalFolder;
var _folder = await rootFolder.CreateFolderAsync(name, CreationCollisionOption.OpenIfExists);
var file = await _folder.CreateFileAsync("test.xml", CreationCollisionOption.OpenIfExists);
}
}
It blocks on the second call to new Cache("test2");
I have not attempted to run your program or reproduce your problem, but I can make an educated guess as to what is going on.
Suppose you wrote yourself the following to-do list:
Put a letter to mom in the mailbox.
Set the alarm to wake me up as soon as I've read her reply.
Go to sleep.
Check the mailbox for the reply.
Read the reply.
Now do everything on that list strictly in order from top to bottom. What happens?
The problem is not with the post office or with mom; they are picking up the letter you put in the mailbox, sending it to mom, mom is writing her reply and the post office is bringing it back to you. The problem is that you never get to the fourth step because you only can start the fourth step after you complete the fifth step and the alarm wakes you up. You'll sleep forever because you are essentially waiting for your future self to wake your present self up.
Eric, Thank you for the explanation.
You're welcome.
However, I am still confused as to why my code does not work.
OK, let's break it down. What does your program really do? Let's simplify:
void M()
{
Task tx = GetATask();
tx.Wait();
}
async Task GetATask()
{
Task ty = DoFileSystemThingAsync();
await ty;
DoSomethingElse();
}
First off: what is a task? A task is an object that represents (1) a job to be done, and (2) a delegate to the continuation of the task: the thing that needs to happen after the task is done.
So you call GetATask. What does it do? Well, the first thing it does is it makes a Task and stores it in ty. That task represents the job "start some operation on the disk, and notify the I/O completion thread when it is done".
What is the continuation of that task? What has to happen after that task is done? DoSomethingElse needs to be called. So the compiler transforms the await into a bunch of code that tells the task to ensure that DoSomethingElse is called when the task is done.
The moment that the continuation of the I/O task has been set, the method GetATask returns a task to the caller. What task is that? This is a different task than the task that got stored into ty. The task that is returned is the task that represents the job do everything that the method GetATask needs to do.
What is the continuation of that task? We don't know! That is up to the caller of GetATask to decide.
OK, so let's review. We have two task objects. One represents the task "go do this thing on the file system". It will be done when the file system does its work. It's continuation is "call DoSomething". We have a second task object that represents the job "do everything in the body of GetATask". It will be done after the call to DoSomethingElse returns.
Again: the first task will be complete when the file I/O succeeds. When that happens, the file I/O completion thread will send a message to the main thread saying "hey, that file I/O you were waiting for is done. I am telling you this because it is now time for you to call DoSomethingElse".
But the main thread is not examining its message queue. Why not? Because you told it to synchronously wait until everything in GetATask, including DoSomethingElse, is complete. But the message that is telling you to run DoSomethingElse now cannot be processed because you are waiting for DoSomethingElse to be complete.
Now is it clear? You are telling your thread to wait until your thread is done running DoSomethingElse before you check to see if "please call DoSomethingElse" is in the queue of work to be performed on this thread! You are waiting until you have read the letter from mom, but the fact that you are waiting synchronously means that you are not checking your mailbox to see if the letter has arrived.
Calling Wait is obviously wrong in this case because you are waiting for yourself to do something in the future, and that's not going to work. But more generally, calling Wait completely negates the entire point of being async in the first place. Just don't do that; it doesn't make any sense to say both "I want to be asynchronous" and "but I want to synchronously wait". Those are opposites.
You're using Wait() in the constructor of the Cache class. That's going to block until whatever is currently executing asynchronously has finished.
This is not the way to design this. Constructors and async do not make sense. Perhaps a factory method approach like this would work better:
public class Cache
{
private string cacheName;
private Cache(string cacheName)
{
this.cacheName = cacheName;
}
public static async Cache GetCacheAsync(string cacheName)
{
Cache cache = new Cache(cacheName);
await cache.Initialize();
return cache;
}
private async void Initialize()
{
StorageFolder rootFolder = ApplicationData.Current.LocalFolder;
var _folder = await rootFolder.CreateFolderAsync(this.cacheName, CreationCollisionOption.OpenIfExists);
var file = await _folder.CreateFileAsync("test.xml", CreationCollisionOption.OpenIfExists);
}
}
And then you use it like this:
await Task.WhenAll(Cache.GetCacheAsync("cache1"), Cache.GetCacheAsync("cache2"), Cache.GetCacheAsync("cache3"));
TestRetrieve(name).Wait();
You're telling it to block specifically by using the .Wait() call.
Remove the .Wait() and it shouldn't block anymore.
The existing answers provide very thorough explanations of why it blocks and code examples of how to make it not block, but these many be 'more information' than some users understand. Here is a simpler 'mechanics oriented' explanation..
The way the async/await pattern works, each time you await an async method, you are "attaching" that method's async context to the current method's async context. Imagine await as passing in a magic hidden paramater "context". This context-paramater is what allows nested await calls to attach to the existing async context. (this is just an analogy...the details are more complicated than this)
If you are inside an async method, and you call a method synchronously, that synchronous method doesn't get that magic hidden async context paramater, so it can't attach anything to it. It's then an invalid operation to create a new async context inside that method using 'wait', because the new context does not get attached to your thread's existing top-level async context (because you don't have it!).
Described in terms of the code-example, the TestRetrieve(name).Wait(); is not doing what you think it's doing. It's actually telling the current thread to re-enter the async-activity-wait-loop at the top. In this example, this is the UI-thread, which is called your OnTest handler. The following picture may help:
UI-thread context looks like this...
UI-Thread ->
OnTest
Since you didn't have a connected chain of await/async calls all the way down, you never "attached' the TestRetrieve async context to the above UI-Thread async chain. Effectively, that new context you made is just dangling off in nowhere land. So when you "Wait" the UIThread, it just goes right back to the top.
For async to work, you need to keep a connected async/await chain from the top-level synchronous thread (in this case it's the UI-thread doing this) through all async actions you need to do. You can't make a constructor async, so you can't chain an async context into a constructor. You need to construct the object synchronously and then await TestRetrieve from outside. Remove the 'Wait' line from your constructor and do this...
await (new Cache("test1")).TestRetrieve("test1");
When you do this, the 'TestRetrieve' async context is properly attached, so the chain looks like this:
UI-Thread ->
OnTest ->
TestRetrieve
Now the UI-thread async-loop-handler can properly resume TestRetrieve during async completions and your code will work as expected.
If you want to make an 'async constructor', you need to do something like Drew's GetCacheAsync pattern, where you make a static Async method which constructs the object synchronously and then awaits the async method. This creates the proper async chain by awaiting and 'attaching' the context all the way down.

Categories

Resources