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.
Related
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.
I've read all I can find on async programming in asp.net (c#). I've made sense of most of how it's supposed to work and when it should be used. Yet I find basic examples not working as I expect. Without Task.Run it doesn't seem to actually run asynchronously.
Can someone tell me what I'm missing in this example?
Say the code is like so
public async Task SubTask2()
{
LongRunningOperation2();
Response.Write("<br>------------------------ Finished -------------------------<br>");
}
private async Task<Boolean> LongRunningOperation1()
{
int counter;
for (counter = 0; counter < 50000; counter++)
{
Response.Write(counter + "<br>");
}
return await Task.FromResult<bool>(true);
}
private async Task<Boolean> LongRunningOperation2()
{
await LongRunningOperation1();
Response.Write("<br>------------------------ Long Task -------------------------<br>");
return true;
}
Shouldn't LongRunningOperation2() return to SubTask2() and print "finished" before or while writing out numbers? Instead it prints finished at the end. Using Task.Run works as expected but then I don't see the point of ever not using Task.Run
A design consideration of the async/await pattern is that sometimes code that has an async signature might return synchronously (immediately) - perhaps due to caching or local data buffering (reading data from a socket, perhaps, and having spare data left to consume from the buffer), or perhaps due to IoC etc providing a synchronous implementation of an asynchronous signature. In that scenario, the entire engine is designed to optimize by not doing anything as callbacks, but continuing to run synchronously. This is not an edge-case - recent C# updates have extended this by adding support for custom awaitables (in particular: ValueTask<T>) to make this even more efficient in the case when something completes with a synchronous but non-trivial result.
The purpose of async is to facilitate scenarios that have genuinely async components, freeing up the thread to do more useful things than waiting for an async operation to complete. It is not about parallelization.
In your case, all of your code is actually synchronous, so it continues to run synchronously all the way through.
First, you're missing await in SubTask2(), so it actually runs synchronously (waits for LongRunningOperation2() to finish).
Secondly, even with asynchronous execution, "finished" wouldn't be printed before LongRunningOperation2() finished it's work. The point of using it is to free the thread, so it can do some other work in the meantime (e.g. handle another request).
I'm trying to use a ManualResetEvent to block until a callback is executed, but the callback is never reached, even when I try to run the callback on another thread.
waitHandle = new ManualResetEvent(false);
DataServiceQueryer<MyEntity> dataServiceQueryer = new DataServiceQueryer<MyEntity>(dsQuery.Expression);
ThreadPool.QueueUserWorkItem(new WaitCallback(stateInfo =>
{
dataServiceQueryer.ExecuteQuery();
}));
// waits here forever
waitHandle.WaitOne();
public class DataServiceQueryer<T>
{
//field, properties
public void ExecuteQuery()
{
// this block is definitely executed
_asyncResult = _query.BeginExecute(new AsyncCallback(c =>
{
// this is never reached
QueryOperationResponse<T> result = _query.EndExecute(c) as QueryOperationResponse<T>;
MainPage.ListRecords = new ObservableCollection<T>(result) as ObservableCollectionEx<MyEntity>;
MainPage.waitHandle.Set();
}), _query);
// neither is this!
var test = _asyncResult.AsyncWaitHandle.WaitOne(0);
}
}
Any suggestions? I am most confounded as to why the _asycResult assignment never seems to take place. I'm using Silverlight 4 with EF4 and the devart Oracle dotConnect provider.
In silverlight and on the ui thread, that is expected behavior (hung app). I cannot seem to find more official documentation, though I could swear I remember seeing it in the past...
I do not remember the exact details but I'm fairly certain directly blocking the ui thread causes everything to stop functioning. I seem to remember that the UI thread handles network IO.
Whatever you want to happen after the WaitOne call needs to be moved to a callback.
Although, it is not your exact situation, there is related info in this link. It explains that blocking the UI thread prevents the web service call from going out since it also blocks the UI messaging queue. I realize that your call is going out from the threadpool. I still think that blocking the ui thread will interfere, but I can't locate the documentation concretely explaining why.
http://www.codeproject.com/Articles/31018/Synchronous-Web-Service-Calls-with-Silverlight-Dis (best I can find at the moment, I'll update when/if I found the article I'm looking for).
While attempting to send a message for a queue through the BeginSend call seem te behave as a blocking call.
Specificly I have:
public void Send(MyMessage message)
{
lock(SEND_LOCK){
var state = ...
try {
log.Info("Begin Sending...");
socket.BeginSend(message.AsBytes(),0, message.ByteLength, SocketFlags.None,
(r) => EndSend(r), state);
log.Info("Begin Send Complete.");
}
catch (SocketException e) {
...
}
}
}
The callback would be something like this:
private void EndSend(IAsyncResult result) {
log.Info("EndSend: Ending send.");
var state = (MySendState) result.AsyncState;
...
state.Socket.EndSend(result, out code);
log.Info("EndSend: Send ended.");
WaitUntilNewMessageInQueue();
SendNextMessage();
}
Most of the time this works fine, but sometimes it hangs. Logging indicates this happens when BeginSend en EndSend are excecuted on the same Thread. The WaitUntilNewMessageInQueue blocks until there is a new message in the queue, so when there is no new message it can wait quit a while.
As far as I can tell this should not really be a problem, but in the some cases BeginSend blocks causing a deadlock situation where EndSend is blocking on WaitUntilNewMessageInQueue (expected), but Send is blocking on BeginSend in return as it seems te be waiting for the EndSend callback te return (not expected).
This behaviour was not what I was expecting. Why does BeginSend sometimes block if the callback does not return in timely fashion?
First of all, why are you locking in your Send method? The lock will be released before the send is complete since you are using BeginSend. The result is that multiple sends can be executing at the same time.
Secondly, do not write (r) => EndSend(r), just write EndSend (without any parameters).
Thrid: You do not need to include the socket in your state. Your EndSend method is working like any other instance method. You can therefore access the socket field directly.
As for your deadlocks, it's hard to tell. You delegate may have something to do with it (optimizations by the compiler / runner). But I have no knowledge in that area.
Need more help? Post more code. but I suggest that you fix the issues above (all four of them) and try again first.
Which operating system are you running on?
Are you sure you're seeing what you think you're seeing?
The notes on the MSDN page say that Send() CAN block if there's no OS buffer space to initiate your async send unless you have put the socket in non blocking mode. Could that be the case? Are you potentially sending data very quickly and filling the TCP window to the peer? If you break into the debugger what does the call stack show?
The rest is speculation based on my understanding of the underlying native technologies involved...
The notes for Send() are likely wrong about I/O being cancelled if the thread exits, this almost certainly depends on the underlying OS as it's a low level IO Completion Port/overlapped I/O issue that changed with Windows Vista (see here: http://www.lenholgate.com/blog/2008/02/major-vista-overlapped-io-change.html) and given that they're wrong about that then they could be wrong about how the completions (calls to EndSend() are dispatched on later operating systems). From Vista onwards it's possible that the completions could be dispatched on the issuing thread if the .Net sockets wrapper is enabling the correct options on the socket (see here where I talk about FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)... However, if this were the case then it's likely that you'd see this behaviour a lot as initially most sends are likely to complete 'in line' and so you'd see most completions happening on the same thread - I'm pretty sure that this is NOT the case and that .Net does NOT enable this option without asking...
This is how you check if it completed synchronously so you avoid the callback on another thread.
For a single send:
var result = socket.BeginSend(...);
if (result.CompletedSynchronously)
{
socket.EndSend(result);
}
For a queue of multiple sends, you can just loop and finalize all synchronous sends:
while (true)
{
var result = socket.BeginSend(...);
if (!result.CompletedSynchronously)
{
break;
}
socket.EndSend(result);
}
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.