Call an awaitable method inside a Thread in C# - 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.

Related

What happens when async code attempts to resume on a thread that is already executing?

I feel that the answer to this is due to me having an incorrect concept of how threads work, but here goes.
private void button1_Click(object sender, EventArgs e)
{
this.TestMethodAsync(); // No await, i.e. fire and forget
// ** Some code here to perform long running calculation (1) **
}
private async Task TestMethodAsync()
{
// Some synchronous stuff
await Task.Delay(1000);
// ** Some code here to perform long running calculation (2) **
}
First of all, I would not "fire and forget" an asynchronous method like this (I would use Task.Run) but I've come across code that does, and I'm trying to understand what the effect is.
In a WinForms application, which uses a WindowsFormsSynchronizationContext, my understanding of async and await tells me that when I click button1, the method will start synchronously on the UI thread. It will call TestMethodAsync and run synchronously until it reaches the await. It will then capture the context, start the Task.Delay task, and yield control to the caller. Since we are not awaiting this call, button1_Click will continue on the UI thread and start performing calculation (1).
At some point, Task.Delay(1000) will complete. A continuation will then run the remainder of the TestMethodAsync method using the captured context, which in this case means that the continuation will be run on the UI thread. This will now start performing calculation (2).
We now have two separate sections of code wanting to run on the same thread (the UI thread) at the same time. My investigations into this seem to suggest that the thread switches back and forth between the two sections of code in order to perform them both.
QUESTION:
I'm confused about exactly what is going on here. How is it possible to resume on a thread that is already running other code? What forces the thread to switch between the two sections of code that want to run? In general, what happens when you attempt to resume on a thread that is already running some other code?
(I suppose this isn't any different to how my click event runs on the UI thread in the first place, in as much as I know it runs on the UI thread, and I know the UI thread is also doing other stuff, but I've not really thought about it like this before.)
This is the secret that you do not understand: I give you the Windows Message Loop
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
BOOL bRet;
while(TRUE)
{
bRet = GetMessage(&msg, NULL, 0, 0);
if (bRet <= 0) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
This is the actual "main" of your application; you just don't see it because it is hidden behind the scenes.
A simpler loop could not be imagined. It gets a message from the queue. If there are no more messages then the program must be done. If there was a message then it runs the standard message translations and dispatches the message, and then keeps on running.
How is it possible to resume on a thread that is already running other code?
It isn't. "Resuming on a thread that is running other code" is actually putting a message in the queue. That "other code" is being synchronously called by DispatchMessage. When it is done, it returns to the loop, the queue is polled, and the message indicates what code needs to be dispatched next. That then runs synchronously until it returns back to the loop.
What forces the thread to switch between the two sections of code that want to run?
Nothing. That doesn't happen.
In general, what happens when you attempt to resume on a thread that is already running some other code?
The message that describes what continuation needs to be run is queued up.
I suppose this isn't any different to how my click event runs on the UI thread in the first place, in as much as I know it runs on the UI thread, and I know the UI thread is also doing other stuff, but I've not really thought about it like this before.
Start thinking about it.
Click events are exactly the same. Your program is doing something; you click the mouse; the click hander does not interrupt the UI thread and start running new work on it. Rather, the message is queued up, and when your UI thread control returns to the message loop, the click is eventually processed; DispatchMessage causes Button1_OnClick to be invoked via some mechanism in Windows Forms. That's what WinForms is; a mechanism for translating Windows messages into calls to C# methods.
But you already knew that. You know that when an event-driven program does a long-running synchronous operation, that the UI freezes, but that click events are processed eventually. How did you think that happened? You must have understood at some level that they were being queued up for processing later, right?
Exercise: What does DoEvents do?
Exercise: Given what you now know: what could possibly go wrong if you call DoEvents in a loop to unblock your UI?
Exercise: How is await different from DoEvents in a GUI application?
How is it possible to resume on a thread that is already running other code?
It needs to be specifically designed to support it. There needs to be some framework in place that allows the thread to take in work and to then execute that work at some later point in time.
This is how your UI thread works. It has a queue, and whenever you schedule work to be done in the UI thread you add an item to the end of the queue. The UI thread then takes the first item from the queue, executes it, and then when it's done, goes on to the next item, and so on, until you end your application.
What forces the thread to switch between the two sections of code that want to run?
Nothing, because it doesn't do that. It runs one, then when it finishes, it runs the other.
In general, what happens when you attempt to resume on a thread that is already running some other code?
Either someone wrote some custom code to specifically do just that, in which case, it does whatever that code specifically told it to do, or else you can't.

How can implement awaiting manually?

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.

C# Thread.Sleep()

I need somehow to bypass Thread.Sleep() method and don't get my UI Thread blocked, but I don't have to delete the method.
I need to solve the problem without deleting the Sleep method. The Sleep method simulates a delay(unresponsive application). I need to handle that.
An application is considered non-responsive when it doesn't pump its message queue. The message queue in Winforms is pumped on the GUI thread. Therefore, to make your application "responsive", you need to make sure the GUI thread has opportunities to pump the message queue - in other words, it must not run your code.
You mentioned that the Thread.Sleep simulates a "delay" in some operation you're making. However, you need to consider two main causes of such "delays":
An I/O request waiting for completion (reading a file, querying a database, sending an HTTP request...)
CPU work
The two have different solutions. If you're dealing with I/O, the best way would usually be to switch over to using asynchronous I/O. This is a breeze with await:
var response = await new HttpClient().GetAsync("http://www.google.com/");
This ensures that your GUI thread can do its job while your request is pending, and your code will restore back on the UI thread after the response gets back.
The second one is mainly solved with multi-threading. You should be extra careful when using multi-threading, because it adds in many complexities you don't get in a single-threaded model. The simplest way of treating multi-threading properly is by ensuring that you're not accessing any shared state - that's where synchronization becomes necessary. Again, with await, this is a breeze:
var someData = "Very important data";
var result = await Task.Run(() => RunComplexComputation(someData));
Again, the computation will run outside of your UI thread, but as soon as its completed and the GUI thread is idle again, your code execution will resume back on the UI thread, with the proper result.
something like that maybe ?
public async void Sleep(int milliseconds)
{
// your code
await Task.Delay(milliseconds); // non-blocking sleep
// your code
}
And if, for reasons that escape me, you HAVE to use Thread.Sleep, you can handle it like that :
public async void YourMethod()
{
// your code
await Task.Run(() => Thread.Sleep(1000)); // non-blocking sleep using Thread.Sleep
// your code
}
Use MultiThreading.
Use a different thread for sleep rather than the main GUI thread. This way it will not interfere with your Main application

BeginFlush seems to work synchronously

I'm trying to use HttpResponse BeginFlush and EndFlush methods in order to make the flush async, which means my worker thread won't being used while flushing to the stream.
However it seems that the BeginFlush methods run in synchronous way always.
I dig in Microsoft reference code and didn't find the reason for this behavior.
This is Microsoft implementation: http://referencesource.microsoft.com/#System.Web/HttpResponse.cs,f121c649c992c407
I checked the SupportsAsyncFlush flag and I'm getting true , so my environment actually supports the AsyncFlush.
Any idea?
This is a code snippet for trying to do the async flush, but I'm not getting to the "Different Threads" line - it is always the same thread that runs this code.
Context.Response.Write("Some message");
Context.Response.BeginFlush(
res =>
{
try
{
var previousThreadId = (int)res.AsyncState;
var thread2Id = Thread.CurrentThread.ManagedThreadId;
if (previousThreadId != thread2Id)
{
Console.WriteLine("Different Threads");
}
Context.Response.EndFlush(res);
}
catch (Exception e)
{
}
},
Thread.CurrentThread.ManagedThreadId);
The code is asynchronous, but it's not multithreaded. You're defining a callback; a method that will be run at some indeterminate point in the future when the flush finishes. That doesn't necessarily mean that it'll run on another thread.
There are also many implementations of abstract functionality in .NET where the behavior is defined as asynchronous, but the implementation is synchronous because that particular implementation expects to run so quickly as to not warrant asynchrony. This is true for a fair bit of .NET's file IO. If the writer you're using expects to be able to flush the buffer very quickly, it may not bother doing it asynchronously.
The effect you are seeing may be related to SycnhronizationContext used by ASP.NET. Depending on .NET version and whether your code executes under ASP.NET page or something else, the behavior may change. Generally, it is normal for the SynchronizationContext to execute the callback on the same thread which started the async operation. You can find more info here: https://msdn.microsoft.com/en-us/magazine/gg598924.aspx
In any case, you can check whether the callback is synchronous or not by checking weather the next line of your code (after BeginFlush) executes before the callback. That will indicate that the callback is indeed asynchronous.

Do asynchronous web service calls always call the AsyncCallback?

I'm making asynchronous web service calls from a C# app:
{
//Put UI in 'loading' state
...
//Now call web service
webServiceProxy.BeginMyMethod(param, new AsyncCallback(MyCallback), null);
}
private void MyCallback(IAsyncResult res)
{
...
//process result
// Put UI back in normal state (yes I'm marshalling back to the UI thread)
}
The main thread puts the app in a "waiting" mode, and then the end of the Callback function re-enables the controls. I'm seeing a bug that occasionally, the UI is stuck forever in the loading mode.
Now there may just be a bug in the callback code (there's quite a bit there), but my question to the community here is this:
Is "MyCallback" GUARANTEED to be called? Presuming that "BeginMyMethod" didn't throw an exception, can I be sure that MyCallback will be executed? I'm seeing a "CompletedSynchronously" and "IsCompleted" on the IAsyncResult returned by the BeginXXX functions, but I'm not sure if that's important or not.
Yes, the callback is guaranteed to be called. The callback is what permits asynchronous code using the Begin* / End* pattern to be written in a continuation-passing style.
You must call the corresponding End* method in your callback (normally, the first thing in the callback), however. It is how the asynchronous method signals an exception that may have occurred during the call, for one thing, as well as the way to get a result out (if any).
Coding the asynchronous pattern using anonymous delegates when using C# 2.0 is sometimes more elegant, and permits writing of the post-call continuation close to the initiation of the call, as well as permitting much easier data sharing through captured variables, providing that appropriate synchronization measures are used.
Ref: http://msdn.microsoft.com/en-us/library/ms228972.aspx:
Applications that can do other work while waiting for the results of an asynchronous operation should not block waiting until the operation completes. Use one of the following options to continue executing instructions while waiting for an asynchronous operation to complete:
Use an AsyncCallback delegate to process the results of the asynchronous operation in a separate thread. This approach is demonstrated in this topic.
[...]
The AsyncCallback will be called regardless of whether the operation was completed synchronously or asynchronously.
I believe the callback is not guaranteed to be called if the CompletedSynchronously property is true.

Categories

Resources